我有一个结果,我没想到多重继承,virtual
方法和指向基类的指针。
使用d.getStr()
,当d
是derived
个实例时,会调用base_2
版本,正如我预期的那样。
使用p->getStr()
,当p
是指向derived
实例的指针(或指向base_2
实例的derived
指针)时,{正如我所料,调用{1}}版本。
但是对于base_2
,当p->getStr()
是指向p
实例的base_1
的指针时,derived
版本被调用,我确信将被称为base_1
版本(感谢base_2
以及using
为getStr()
方法的事实)。
以下是一个简单的例子:
virtual
输出如下
#include <iostream>
struct base_1
{
virtual std::string getStr () const
{ return "string from base 1"; }
};
struct base_2
{
virtual std::string getStr () const
{ return "string from base 2"; }
};
struct derived : public base_1, public base_2
{
using base_2::getStr;
};
int main ()
{
derived d;
derived * dp = &d;
base_1 * bp1 = &d;
base_2 * bp2 = &d;
std::cout << "from derived: " << d.getStr() << std::endl;
std::cout << "from derived pointer: " << dp->getStr() << std::endl;
std::cout << "from base_1 pointer: " << bp1->getStr() << std::endl;
std::cout << "from base_2 pointer: " << bp2->getStr() << std::endl;
}
我知道,要强制调用from derived: string from base 2
from derived pointer: string from base 2
from base_1 pointer: string from base 1
from base_2 pointer: string from base 2
版本,我可以在base_2
中添加以下方法
derived
但我的问题是:
1)为什么指向std::string getStr () const
{ return base_2::getStr(); }
(指向派生实例)的指针忽略base_1
指令并调用using
base_1
版本?
2)当getStr()
指针使用base_2
实例而没有重新定义getStr()
时,是否有办法强加derived
base_1
版本getStr()
?
---编辑---
感谢您的回答。
我知道你在描述正在发生的事情,但我怀疑的是:语言(标准)是否描述了这方面的内容?或者它是一个未定义的部分?
我的意思是:如果我删除using
指令,我会从error: request for member getStr is ambiguous
和d.getStr()
收到编译错误(dp->getStr()
),因为编译器没有知道要选择哪个版本的getStr()
。
但getStr()
是virtual
方法。所以(我确信)一个基指针应该使用它们的派生版本。但我们有几种相互碰撞的方法。
从语言(标准)的角度来看,base_1
(或base_2
)是指定(或有义务)选择碰撞方法的两个版本中的一个而忽略另一个的指针吗?
也许我错了,但在我看来,virtual
方法以非virtual
方法进行管理。
答案 0 :(得分:4)
您希望以下列方式使用using
关键字:
struct derived : public base_1, public base_2
{
using base_2::getStr;
};
这与:
相同struct derived : public base_1, public base_2
{
void getStr()
{
base_2::getStr();
}
};
在这种情况下,您期望的行为 - 当p是指向p->getStr()
的指针时调用base_1
- 实际上最终会调用base_2::getStr()
。 derived
会覆盖base_1
&#39; getStr()
,因此通过普通指针调用base_1
&#39; getStr
()会导致{ {1}} derived
()被调用,调用getStr
base_2
方法。
但是,这不是发生的事情。 getStr()
关键字不是以这种方式转发方法调用的别名。 using
关键字不会在using
&lt; d;类中创建方法,因此类继承不受影响,derived
&#39; s derived_1
不会在subclsas中获得覆盖。这就是为什么调用getStr()
&#39; derived_1
无法调用getStr()
derived_2
。
答案 1 :(得分:2)
这是因为派生类必须为$ which python
/Users/PatrickT/miniconda3/bin/python
提供2个vtable条目,每个基类一个,因此它可以正确解析getStr()
和base_1::getStr()
。 base_2::getStr()
指令不创建using
vtable条目或替换基类条目,它只选择将使用哪个基类条目。当通过指向derived::getStr()
的指针时,编译器只会&#34;看到&#34;来自base_1
和derived
的虚拟函数的vtable条目,因此它将base_1
解析为getStr()
。您在base_1::getStr()
中添加显式getStr()
的解决方案可能是最干净的,但为了清晰起见,最好使其与基类匹配。
答案 2 :(得分:0)
1)似乎你的代码完全按照它应该做的去做。您指向base_1,因此您从base_1(或其任何基类)获取函数。该对象由base_1和base_2组成,此时未知,因为您指的是基类,而不是派生类。
2)不,这根本不可能。你必须在derived
中重载getStr()。