[英]C++ base class function call from last derived in diamond design
I'm learning C++ and after having read and tested a lot about multiple inheritance, virtual inheritance/methods and diamond design I still have some problems to understand it till the end. 我正在学习C ++,在阅读和测试了很多有关多重继承,虚拟继承/方法和钻石设计的知识之后,直到最后我仍然有一些问题需要理解。
I'm in the diamond design pattern, where class B e C inherit virtual public A
and D inherits public B, public C
: 我处于菱形设计模式中,其中类B e C继承
virtual public A
而类D继承public B, public C
:
A
/ \
B C
\ /
D
All classes implement a private variable std::string _message
that I initialize with the following string. 所有类都实现了一个私有变量
std::string _message
,我使用以下字符串对其进行了初始化。
"class-name instance"
Only Class A
implements a virtual public display(void) const
method too. 仅
Class A
实现了一个virtual public display(void) const
方法。
void display(void) const{
std::cout << this->_message << std::endl;
}
The main is: 主要是:
D foo;
foo.display();
The output is: 输出为:
A instance
However when I "inspect" the element debugging step by step with Xcode I see that inside the D instance I can correctly find a B, a C and A object (just one shared by B and C) with all the different _message
correctly assigned. 但是,当我使用Xcode逐步“检查”元素调试时,我发现在D实例内部,我可以正确找到一个B,一个C和A对象(B和C共享一个对象),并正确分配了所有不同的
_message
。
What I'm doing wrong? 我做错了什么? Need I override the
display()
method in D class? 我需要重写D类中的
display()
方法吗? But if so, which is the real point of multiple inheritance if I have to re-implements the same method in a derived class? 但是,如果是这样,如果我必须在派生类中重新实现相同的方法,那么多重继承的真正意义是什么?
Your question seems to not be related to the diamond pattern, but is generally about the inheritance model in C++. 您的问题似乎与菱形图案无关,但通常与C ++中的继承模型有关。 Most things in C++ are statically bound, so at compile time the compiler fixes what method or member of a certain name is used:
C ++中的大多数东西都是静态绑定的,因此在编译时,编译器会修复使用哪种方法或某个名称的成员:
If you access a member of the implicit this
object or using a pointer or reference to an object, you will end up accessing a member of the class the pointer or reference has at compile time, no matter whether at runtime there is a derived-class object that has members of the same name. 如果访问隐式
this
对象的成员,或者使用指针或对对象的引用,那么无论在运行时是否存在派生类,最终都将在编译时访问指针或引用所具有的类的成员具有相同名称成员的对象。 That's why they say you can not override but just shadow members in base classes when you define an equal named member in the derived class. 这就是为什么他们说,当您在派生类中定义一个相等的命名成员时,您不能覆盖而只能覆盖基类中的影子成员。
The same thing is true for non-virtual functions. 非虚拟功能也是如此。
The only thing that behaves different is virtual functions. 唯一表现不同的是虚函数。 These functions can be overwritten in derived classes, and code that gets handed a pointer-to-base-class can virtual functions of the base class and end up executing implementations given in the derived class.
可以在派生类中覆盖这些函数,并且将指针传递给基类的代码可以虚化基类的功能,并最终执行派生类中给定的实现。
So the point of virtual functions is not to have the compiler reinterpret a certain function in the context of derived classes (as you seem to understand it), but to make it possible to replace a function in the base class by a different function in the derived class. 因此,虚函数的意义不在于让编译器在派生类的上下文中重新解释某个函数(如您所理解的那样),而是可以用一个不同的函数替换基类中的函数。派生类。
To go back to your motivation: If you want a display
function that prints a message that depends on the actual object type, the thing that is fixed is the printig, which doesn't need to be virtual. 回到您的动机:如果您想要一个
display
功能来打印一条消息,该消息取决于实际的对象类型,则固定的是printig,它不需要是虚拟的。 But you need a virtual function to obtain the object type. 但是您需要一个虚拟函数来获取对象类型。 Like this:
像这样:
#include <iostream>
#include <ostream>
class A {
public:
void display() { std::cout << get_message() << '\n'; }
virtual const char * get_message() { return "A instance"; }
};
class B : virtual public A {
public:
virtual const char * get_message() { return "B instance"; }
};
class C : virtual public A {
public:
virtual const char * get_message() { return "C instance"; }
};
class D : public B, public C {
public:
// virtual const char * get_message() { return B::get_message(); }
// virtual const char * get_message() { return C::get_message(); }
// virtual const char * get_message() { return "D instance"; }
};
int main(void)
{
D foo;
foo.display();
A* a_ptr = &foo;
a_ptr->display();
return 0;
}
The example as given will not compile (now this is due to the diamond pattern), because the compiler can not decide, what overrider of A::get_message()
, either B::get_message()
or C::get_message()
should be picked in D objects, you need to make one of the comments in D real code to declare the one-and-only get_message
for D, in which can re-use the existing functions. 给出的示例将无法编译(现在这是由于菱形图案引起的),因为编译器无法确定
A::get_message()
替代方法, B::get_message()
还是C::get_message()
在D对象中被选中后,您需要在D实代码中进行注释之一,以声明D的唯一get_message
,在其中可以重用现有功能。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.