Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/161.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如果类继承自2个模板化父类,则调用不明确。为什么?_C++_Templates_Multiple Inheritance_Visual C++ 2010 - Fatal编程技术网

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

C++ 如果类继承自2个模板化父类,则调用不明确。为什么?,c++,templates,multiple-inheritance,visual-c++-2010,C++,Templates,Multiple Inheritance,Visual C++ 2010,我有一个模板类,它对作为模板参数给定的类执行操作。对于我的一些类,我希望将功能“分组”到一个类中,以便于调用方使用。事实上,代码如下所示(名称已更改): 模板 类DoSomeProcessing { 公众: 工艺(T&T); }; 类处理前端:public DoSomeProcessing,public DoSomeProcessing { }; 问题是,当我使用CustomerOrder作为参数调用ProcessingFrontEnd::process时,编译器会对此进行抱怨 我试图在一个较

我有一个模板类,它对作为模板参数给定的类执行操作。对于我的一些类,我希望将功能“分组”到一个类中,以便于调用方使用。事实上,代码如下所示(名称已更改):

模板
类DoSomeProcessing
{
公众:
工艺(T&T);
};
类处理前端:public DoSomeProcessing,public DoSomeProcessing
{
};
问题是,当我使用CustomerOrder作为参数调用ProcessingFrontEnd::process时,编译器会对此进行抱怨

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

#include <vector>

class X : public std::vector<char>
        , public std::vector<void *>
{
};

int main(void)
{
X x;
x.push_back('c');
return 0;
}
#包括
X类:公共标准::向量
,公共标准::向量
{
};
内部主(空)
{
X;
x、 推回(“c”);
返回0;
}
事实上,如果对其进行编译,Microsoft的VS2010编译器会给出以下错误:

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
test.cpp
test.cpp(11):错误C2385:对“push_back”的访问不明确
可能是基“std::vector”中的“push_back”
或者可以是基“std::vector”中的“push_back”
test.cpp(11):错误C3861:“推回”:找不到标识符
我使用不同的类型(char+void*、double+void*)和调用('c',3.14)中的不同参数测试了这个测试应用程序,但是错误消息总是一样的

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

为什么编译器不能确定要调用的正确函数?是什么让编译器感到困惑?或者它只是Microsoft编译器中的一个bug

编辑: 如果我显式地向类中添加2个push_-back方法,如下所示:

class X : public std::vector<char>
        , public std::vector<void *>
{
public:
   void push_back(char c) {}
   void push_back(void *p) {}
};
X类:公共标准::向量 ,公共标准::向量 { 公众: void push_back(char c){} void推回(void*p){ };
编译器不再抱怨了。因此,通过这些方法,他可以清楚地区分字符和空指针。如果这两个push_-back方法是从父级继承的,为什么他不能这样做呢?

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


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

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


解决方法是在派生类中使用语句显式地
,从每个模板基类中引入每个重载

这是设计的。编译器未尝试解析重载 函数,因为它们没有重载 功能。这方面的标准非常明确 (见10.2.2)。如果在两个文件中找到相同的名称 不同的基础,这是一个模棱两可的问题,即使它们 可以通过呼叫正确解决(即在 你的情况)。不同类中的相同命名函数通常具有完全不同的用途,因此不应基于 他们的论点。有很多很好的理由不这样做 允许,但这里有一个

想象你的C类来自A和B,然后 这两个基类来自两个不同的 图书馆。如果B的作者添加了一个新函数 对于类,它可能会通过 将调用从a::foo()重定向到B::foo(),如果 后者更适合

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

using std::vector<char>::push_back;
using std::vector<void *>::push_back;
使用std::vector::push_back;
使用std::vector::push_-back;

对于类X的声明。

除非你知道自己在做什么,否则从std容器中插入是个坏主意。@Stephane,我知道,但这只是用一种更简单的方式来说明问题。实际上,我是从自己的模板类继承的,而不是从std容器继承的?
CustomerOrder
ProductionOrder
是不相关的类吗?(正如Stephane指出的那样,您的测试应用程序不是一个很好的匹配,标准容器中充满了普通类通常不具备或不需要的有趣技巧,此外,空指针和整数类型(如字符)有点太接近,无法轻松解决重载问题。最好提供有关实际问题的更多信息。)CustomerOrder和ProductionOrder是不相关的类。在我的实际示例和测试示例中,错误消息是相同的。这是他抱怨的调用。编译器从模板类型知道这一点。示例中的第一个父类(std::vector)有一个方法push_back(char),而第二个父类(std::vector)有一个方法push_back(void*)。为什么在我的类中有两个PosiSeBoBead方法不同?看起来类似于“名字隐藏”-但是,在C++标准中隐藏基本的范围不适用于这种情况。浏览basic.lookup可能会发现一个显式或隐式的规则,这可能仍然无法为您提供基本原理。用户显然希望调用最佳匹配函数。就像任何超负荷解决方案一样。是的,就是这样。显然,这是为了防止用户错误,而不是编译器无法解决的问题。添加using子句确实解决了这个问题。谢谢。帕特里克,它只是C++中许多不一致的领域之一。普通成员函数的设计坚持重载不会跨作用域工作,“想象你的类C派生自A和B,而这两个基类来自两个不同的库。”现在,想象一下名称空间的相同情况。不同的、不一致的规则。
using std::vector<char>::push_back;
using std::vector<void *>::push_back;