[英]C++ base class function call from last derived in diamond design
我正在学习C ++,在阅读和测试了很多有关多重继承,虚拟继承/方法和钻石设计的知识之后,直到最后我仍然有一些问题需要理解。
我处于菱形设计模式中,其中类B e C继承virtual public A
而类D继承public B, public C
:
A
/ \
B C
\ /
D
所有类都实现了一个私有变量std::string _message
,我使用以下字符串对其进行了初始化。
"class-name instance"
仅Class A
实现了一个virtual public display(void) const
方法。
void display(void) const{
std::cout << this->_message << std::endl;
}
主要是:
D foo;
foo.display();
输出为:
A instance
但是,当我使用Xcode逐步“检查”元素调试时,我发现在D实例内部,我可以正确找到一个B,一个C和A对象(B和C共享一个对象),并正确分配了所有不同的_message
。
我做错了什么? 我需要重写D类中的display()
方法吗? 但是,如果是这样,如果我必须在派生类中重新实现相同的方法,那么多重继承的真正意义是什么?
您的问题似乎与菱形图案无关,但通常与C ++中的继承模型有关。 C ++中的大多数东西都是静态绑定的,因此在编译时,编译器会修复使用哪种方法或某个名称的成员:
如果访问隐式this
对象的成员,或者使用指针或对对象的引用,那么无论在运行时是否存在派生类,最终都将在编译时访问指针或引用所具有的类的成员具有相同名称成员的对象。 这就是为什么他们说,当您在派生类中定义一个相等的命名成员时,您不能覆盖而只能覆盖基类中的影子成员。
非虚拟功能也是如此。
唯一表现不同的是虚函数。 可以在派生类中覆盖这些函数,并且将指针传递给基类的代码可以虚化基类的功能,并最终执行派生类中给定的实现。
因此,虚函数的意义不在于让编译器在派生类的上下文中重新解释某个函数(如您所理解的那样),而是可以用一个不同的函数替换基类中的函数。派生类。
回到您的动机:如果您想要一个display
功能来打印一条消息,该消息取决于实际的对象类型,则固定的是printig,它不需要是虚拟的。 但是您需要一个虚拟函数来获取对象类型。 像这样:
#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;
}
给出的示例将无法编译(现在这是由于菱形图案引起的),因为编译器无法确定A::get_message()
替代方法, B::get_message()
还是C::get_message()
在D对象中被选中后,您需要在D实代码中进行注释之一,以声明D的唯一get_message
,在其中可以重用现有功能。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.