代码之家  ›  专栏  ›  技术社区  ›  Filip Frącz

这种继承有什么问题?

  •  4
  • Filip Frącz  · 技术社区  · 17 年前

    #include <map>
    
    
    class A : public std::multimap<int, bool>
    {
    public:
        size_type erase(int k, bool v)
        {
            return erase(k); // <- this fails; had to change to __super::erase(k)
        }
    };
    
    int main()
    {
        A a;
        a.erase(0, false);
        a.erase(0); // <- fails. can't find base class' function?!
    
        return 0;
    }
    
    9 回复  |  直到 17 年前
        1
  •  26
  •   Greg Hewgill    17 年前

    当您在一个类中声明一个与超类同名但签名不同的函数时,名称解析规则规定编译器应该 别看了 对于您试图在找到第一个匹配项后调用的函数。按名称查找函数后, 然后 它应用重载解析规则。

    erase(int, bool) 当你打电话的时候 erase(0) ,然后决定参数不匹配。

        2
  •  17
  •   Stack Overflow is garbage    17 年前

    他说:你需要 极其

    2:这里的超载规则有点古怪。编译器首先查找派生类,如果找到 重载相同的名称,它将停止在那里查看。只有在派生类中未找到重载时,它才会在基类中查找。

    一个简单的解决方案是将基类所需的函数引入派生类的命名空间:

    class A : public std::multimap<int, bool>
    {
    public:
            using std::multimap<int, bool>::erase; // Any erase function found in the base class should be injected into the derived class namespace as well
            size_type erase(int k, bool v)
            {
                    return erase(k);
            }
    };
    

        3
  •  9
  •   J Francis    17 年前

    通过在派生类中定义具有相同名称但参数不同的函数,隐藏了基类的擦除成员函数。

    http://www.parashift.com/c++-faq-lite/strange-inheritance.html#faq-23.9

        4
  •  6
  •   Marcin    17 年前

    首先,永远不要从STL容器派生,因为没有STL容器定义虚拟析构函数。
    其次,请参阅Greg关于继承的回答。

        5
  •  5
  •   Enno    17 年前

    考虑是否真的要从std::map继承。在我编写代码的所有时间里,这比STL存在的时间要长,我从未见过一个实例,其中从std::container继承是最好的解决方案。

    多重地图。

        6
  •  3
  •   Community Mohan Dere    9 年前

    喜欢组合而不是继承。

    C++ Coding Standards Sutter/Alexandrescu在这方面有完整的章节(#34),以及 Google points to many good references 关于这个问题。

    看来有一个 SO thread on the topic as well .

        7
  •  1
  •   bradtgmurray    17 年前

    对于那些使用 Effective C++

        8
  •  1
  •   Andy Balaam    17 年前

    我同意其他人的意见,即您需要非常小心地继承STL类,并且几乎应该始终避免。

    然而,这个问题可能会出现在其他一些基类中,从这些基类继承是完全合理的。

        9
  •  0
  •   Zan Lynx    17 年前

    要以可移植的方式替换_super,请在类的顶部定义一个typedef,如下所示:

    typedef std::multimap<int, bool> parent;
    public:
        size_type erase(int k, bool v)
        {
                return parent::erase(k);
        }
    

    当然,它不需要是“家长”。它可以是您喜欢的任何名称,只要在整个项目中始终使用它。