多重继承模板类

发布于 2024-09-12 03:05:49 字数 1306 浏览 8 评论 0原文

class messageA {
};

class messageB {
};

template<class T>
class queue {
public:
    virtual ~queue() {}
    void submit(T& x) {}
};

class A : public queue<messageA>, public queue<messageB>
{
};

int main()
{
    A aa;
    aa.submit(messageA());
    aa.submit(messageB());
}

我的第一个想法是,上面的代码应该没问题,因为类 A 将包含 2 个重载的提交函数,它们将接受 messageA 和 messageB 对象。

但是,编译器给了我以下错误:

我可以知道为什么存在二义性吗?对于第一次提交调用,我想调用 messageA 版本,这不是很明显吗?对于第二次提交调用,我想调用messageB版本?


------ Build started: Project: main, Configuration: Release Win32 ------
Compiling...
main.cpp
.\main.cpp(21) : error C2385: ambiguous access of 'submit'
        could be the 'submit' in base 'queue<messageA>'
        or could be the 'submit' in base 'queue<messageB>'
.\main.cpp(21) : error C3861: 'submit': identifier not found
.\main.cpp(22) : error C2385: ambiguous access of 'submit'
        could be the 'submit' in base 'queue<messageA>'
        or could be the 'submit' in base 'queue<messageB>'
.\main.cpp(22) : error C2664: 'queue<T>::submit' : cannot convert parameter 1 from 'messageB' to 'messageA &'
        with
        [
            T=messageA
        ]
.\main.cpp(22) : error C3861: 'submit': identifier not found
class messageA {
};

class messageB {
};

template<class T>
class queue {
public:
    virtual ~queue() {}
    void submit(T& x) {}
};

class A : public queue<messageA>, public queue<messageB>
{
};

int main()
{
    A aa;
    aa.submit(messageA());
    aa.submit(messageB());
}

My first thought is, the above code should be fine, as class A will contains 2 overloaded submit functions, which will accept messageA and messageB object.

However, the compiler gives me the following error :

May I know why there is an ambiguous? Isn't it is quite obvious that, for the 1st submit call, I want to call messageA version? For the 2nd submit call, I want to call messageB version?


------ Build started: Project: main, Configuration: Release Win32 ------
Compiling...
main.cpp
.\main.cpp(21) : error C2385: ambiguous access of 'submit'
        could be the 'submit' in base 'queue<messageA>'
        or could be the 'submit' in base 'queue<messageB>'
.\main.cpp(21) : error C3861: 'submit': identifier not found
.\main.cpp(22) : error C2385: ambiguous access of 'submit'
        could be the 'submit' in base 'queue<messageA>'
        or could be the 'submit' in base 'queue<messageB>'
.\main.cpp(22) : error C2664: 'queue<T>::submit' : cannot convert parameter 1 from 'messageB' to 'messageA &'
        with
        [
            T=messageA
        ]
.\main.cpp(22) : error C3861: 'submit': identifier not found

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

倒带 2024-09-19 03:05:49

我现在没有编译器,但我想一个继承可能会隐藏另一个:编译器将使用 Koenig Lookup 找到正确的符号,如果我没记错的话,一旦编译器找到合适的符号(即称为“submit”的方法),它将停止在父作用域和/或外部作用域中搜索其他符号。

在这种情况下,我认为两个继承类都会搜索该符号,但如果没有确切的编译器(Visual C++ 2003?2008?2010?),我无法猜测更多。

经过一番思考,另一种可能性是编译器确实找到了这两个符号,但无法决定调用哪个(在符号解析时,编译器只关心符号名称,而不关心其确切原型)。我相信最后的解释是正确的。

尝试在派生类中添加 using 语句:

class A : public queue<messageA>, public queue<messageB>
{
   using queue<messageA>::submit ;
   using queue<messageB>::submit ;
} ;

将两个提交方法直接引入 A 类作用域中。

另请注意,您的提交方法将消息作为非常量引用,而在构造函数中,您的消息参数是临时参数(因此是 const r 值)。

将 main 重写为:

int main()
{
    A aa;
    messageA mA ;
    messageA mB ;
    aa.submit(mA);
    aa.submit(mB);
}

可以帮助编译(这可以解释第 22 行的编译器错误)。

或者您可以更改提交方法的原型以接受常量引用而不是非常量引用。

注意:仍然没有编译器,所以尝试大脑调试你的代码... :-P ...

I have no compiler right now, but I guess one inheritance could hide the other : The compiler will use Koenig Lookup to find the right symbol, and if I remember correctly, once the compiler find a suitable symbol (i.e., a method called "submit"), it will stop searching for others in parent and/or outer scopes.

In this case, I thought both inheriting classes would be searched for the symbol, but without your exact compiler (Visual C++ 2003 ? 2008 ? 2010 ?), I cannot guess much more.

After some thoughts, another possibility is that the compiler did find both symbols, but is unable to decide which to call (at that moment of symbol resolution, the compiler cares only for symbol name, not its exact prototype). I believe this last explanation to be the right one.

Try adding using statements in your derived classes :

class A : public queue<messageA>, public queue<messageB>
{
   using queue<messageA>::submit ;
   using queue<messageB>::submit ;
} ;

to bring both the submit methods directly in the A class scope.

Note, too, that your submit methods are taking messages as non-const reference, while in the constructor, your message parameters are temporaries (and thus, const r-values).

Re-writting the main as:

int main()
{
    A aa;
    messageA mA ;
    messageA mB ;
    aa.submit(mA);
    aa.submit(mB);
}

could help compile (this could explain the compiler error on line 22).

Or you could change the prototype of your submit methods to accept const references instead of non-const references.

Note: Still without compiler, so trying to brain-debug your code... :-P ...

宫墨修音 2024-09-19 03:05:49
Something* smth1 = ((Base<Something> *)d)->createBase<Something>();

上面的代码工作正常。

Something* smth1 = ((Base<Something> *)d)->createBase<Something>();

The above code works fine.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文