代码之家  ›  专栏  ›  技术社区  ›  Patrick

如果类从2个模板化父类继承,则调用不明确。为什么?

  •  3
  • Patrick  · 技术社区  · 15 年前

    template<typename T>
    class DoSomeProcessing
    {
    public:
       process(T &t);
    };
    
    class ProcessingFrontEnd : public DoSomeProcessing<CustomerOrder>, public DoSomeProcessing<ProductionOrder>
    {
    };
    

    我试图在一个较小的测试应用程序中重现这个问题。代码如下:

    #include <vector>
    
    class X : public std::vector<char>
            , public std::vector<void *>
    {
    };
    
    int main(void)
    {
    X x;
    x.push_back('c');
    return 0;
    }
    

    test.cpp
    test.cpp(11) : error C2385: ambiguous access of 'push_back'
            could be the 'push_back' in base 'std::vector<char,std::allocator<char> >'
            or could be the 'push_back' in base 'std::vector<void *,std::allocator<void *> >'
    test.cpp(11) : error C3861: 'push_back': identifier not found
    

    我用VS2005和VS2010测试了这个,但是我总是得到相同的错误。

    编辑:

    class X : public std::vector<char>
            , public std::vector<void *>
    {
    public:
       void push_back(char c) {}
       void push_back(void *p) {}
    };
    

    编译器不再抱怨了。因此,通过这些方法,他可以清楚地区分字符和空指针。如果这两个push\u back方法是从父级继承的,为什么他不能这样做呢?

    3 回复  |  直到 15 年前
        1
  •  4
  •   David    15 年前

    这是故意的。编译器没有尝试解析重载 因为它们是 超载 功能。这个标准非常明确 (见10.2.2)。如果在两个地方发现相同的名字 不同的基础,这是一个模棱两可的问题,即使它们 你的案子)。不同类中相同的命名函数通常具有完全不同的用途,因此不应基于

    想象你的C类来自A和B,还有 这两个基类来自两个不同的 对于类,它可能会通过 将调用从a::foo()重定向到B::foo(),如果 后者更合适。

    如果您想以相同的方式处理这两个函数 如果是单个类的一部分,那么最好的方法就是使用 派生类中的声明。只需添加

    using std::vector<char>::push_back;
    using std::vector<void *>::push_back;
    

    类的声明。

        2
  •  2
  •   Pontus Gagge    15 年前

    我相信你正在运行C++的重载规则 prohibit overloading across classes . 如果模板类是两个独立的类,每个类都有自己的类,则会得到相同的结果 process(CustomerOrder) process(ProductionOrder) 成员。

    解决方法是明确的 using

        3
  •  -2
  •   Puppy    15 年前

    编译器如何知道要调用哪个进程?有两种选择。两个都要,一个还是另一个?

    您需要重写派生类中的进程。