多重继承,虚方法冲突和基类指针

max*_*x66 5 c++ polymorphism multiple-inheritance language-lawyer

我有一个结果,我没有期望从多个继承,virtual方法和指向基类的指针.


使用d.getStr(),何时dderived实例base_2,正如我所料,调用版本.

随着p->getStr(),当p是一个指向derived实例(或指针base_2指向一个derived实例),该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;
}
Run Code Online (Sandbox Code Playgroud)

输出如下

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
Run Code Online (Sandbox Code Playgroud)

我知道,为了强制调用base_2版本,我可以添加derived以下方法

std::string getStr () const
 { return base_2::getStr(); }
Run Code Online (Sandbox Code Playgroud)

但我的问题是:

1)为什么指向base_1(指向派生实例)的指针忽略using指令并调用base_1版本getStr()

2)有没有办法在没有重新定义的情况下强制使用指针使用实例时的base_2版本?getStr()derivedbase_1getStr()

---编辑---

谢谢你的回答.

我知道你在描述正在发生的事情,但我怀疑的是:语言(标准)是否描述了这方面的内容?或者它是一个未定义的部分?

我的意思是:如果我删除的using指令,我得到一个编译错误(error: request for member getStr is ambiguous),从d.getStr()dp->getStr(),因为编译器不知道哪个版本getStr()来选择.

getStr()virtual方法.所以(我确信)一个基指针应该使用它们的派生版本.但我们有几种相互碰撞的方法.

从语言(标准)的角度来看,一个base_1(或base_2)是指定(或有义务)选择忽略另一个的碰撞方法的两个版本之一的指针?

也许我错了,但在我看来,这样的virtual方法是作为非virtual方法管理的.

JvO*_*JvO 0

1)看起来你的代码正在做它应该做的事情。您指向base_1,因此您可以从base_1(或其任何基类)获取函数。此时该对象由 base_1 和 base_2 组成是未知的,因为您指向基类,而不是派生类。

2)不,那是不可能的。您确实必须重载derived.