问题描述
我有一个意外的结果,那就是多重继承,virtual
方法和基类指针.
I have a result that I didn't expect from multiple inheritance, virtual
methods and pointers to base classes.
对于d.getStr()
,当d
是derived
实例时,将调用base_2
版本,正如我期望的那样.
With d.getStr()
, when d
is a derived
instance, the base_2
version is called, as I expected.
对于p->getStr()
,当p
是指向derived
实例的指针(或指向base_2
的指针指向derived
实例的指针)时,正如我期望的那样,将调用base_2
版本.
With p->getStr()
, when p
is a pointer to a derived
instance (or a pointer to base_2
pointing to a derived
instance), the base_2
version is called, as I expected.
但是使用p->getStr()
时,当p
是指向base_1
的指针,该指针指向derived
实例时,会调用base_1
版本,并且我确信它将被称为base_2
版本(谢谢) using
和getStr()
是virtual
方法的事实).
But with p->getStr()
, when p
is a pointer to a base_1
pointing to a derived
instance, the base_1
version is called and I was convinced would be called the base_2
version (thanks the using
and the fact that getStr()
are virtual
methods).
以下是一个简单的示例:
The following is a simple example:
#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
中添加以下方法
I know that, to impose the call of base_2
version, I can add in derived
the following method
std::string getStr () const
{ return base_2::getStr(); }
但是我的问题是:
1)为什么指向base_1
的指针(指向派生实例)忽略using
指令并调用getStr()
的base_1
版本?
1) Why does the pointer to base_1
(pointing to a derived instance) ignore the using
directive and call the base_1
version of getStr()
?
2)当derived
实例由base_1
指针使用而没有重新定义getStr()
时,有没有办法强加base_2
版本的getStr()
?
2) Is there a way to impose the base_2
version of getStr()
, when derived
instance is used by a base_1
pointer, without redefining getStr()
?
---编辑---
感谢您的回答.
我了解您正在描述正在发生的事情,但我的疑问是:语言(标准)是否描述了这方面?还是未定义的部分?
I understand that you are describing what's happening but my doubt is: does the language (the standard) describe this aspect? Or is it an undefined part?
我的意思是:如果删除using
指令,则会从d.getStr()
和dp->getStr()
收到编译错误(error: request for member getStr is ambiguous
),因为编译器不知道将哪个版本的getStr()
选择.
I mean: if I remove the using
directive, I get a compilation error (error: request for member getStr is ambiguous
), from d.getStr()
and from dp->getStr()
, because the compiler doesn't know which version of getStr()
to chose.
但是getStr()
是virtual
方法.因此(我坚信)基本指针应使用它们的派生版本.但是我们有两种碰撞方法.
But getStr()
are virtual
methods. So (I was convinced that) a base pointer should use the derived version of they. But we have a couple of colliding methods.
从语言(标准)的角度来看,base_1
(或base_2
)是指针被授权(或必须)选择碰撞方法的两个版本中的一个而忽略另一个的指针吗?
From the language (standard) point of view, a base_1
(or base_2
) is the pointer authorized (or obligated) to choose one of the two versions of the colliding methods ignoring the other?
也许我错了,但在我看来,以这种方式,virtual
方法被作为非virtual
方法管理.
Maybe I'm wrong but seems to me that, in this way, the virtual
methods are managed as non virtual
methods.
推荐答案
您期望通过以下方式使用using
关键字:
You are expecting that when you using the using
keyword in the following manner:
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->getStr()
(当p是指向base_1
的指针时)的确会最终调用base_2::getStr()
. derived
覆盖base_1
的getStr()
,因此通过普通指针调用base_1
的getStr
()会导致调用derived
的getStr
(),从而调用 getStr()
方法.
In this case, the behavior you are expecting -- invoking p->getStr()
, when p is a pointer to a base_1
-- would, indeed, end up invoking base_2::getStr()
. derived
overrides base_1
's getStr()
, so invoking base_1
's getStr
(), through an ordinary pointer, results in derived
's getStr
() getting invoked, which invokes base_2
getStr()
method.
但是,这不会发生. using
关键字不是以这种方式转发方法调用的别名. using
关键字不会在derived
的类中创建方法,因此类继承不会受到影响,并且derived_1
的getStr()
不会在子clsas中被覆盖.这就是为什么调用derived_1
的getStr()
不会结束调用derived_2
的getStr()
的原因.
However, this is not what happens. The using
keyword is not an alias for forwarding a method call in this manner. The using
keyword does not create a method in derived
'd class, so class inheritance is not affected, and derived_1
's getStr()
does not get overriden in the subclsas. And that's why invoking derived_1
's getStr()
does not wind up invoking derived_2
's getStr()
.
这篇关于多重继承,虚拟方法冲突和来自基类的指针的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!