sho*_*osh 17 c++ virtual-functions multiple-inheritance diamond-problem
我有一个像这样的钻石多重继承场景:
A
/ \
B C
\ /
D
Run Code Online (Sandbox Code Playgroud)
公共父A定义了虚函数fn().
B和C都可以定义fn()吗?
如果是,那么下一个问题是 - D可以访问B和C的fn()而不消除歧义吗?我假设有一些语法...
而D是否有可能在不知道谁是B和C的情况下做到这一点?B和C可以替换为其他类,我希望D中的代码是通用的.
我想要做的是让D以某种方式枚举它在其祖先中具有的fn()的所有实例.这是否可能在某些其他方面表示虚函数?
Joh*_*itb 19
除非你fn再次覆盖D,否则不可能.因为D对象中没有最终覆盖:Both C和B覆盖A::fn.你有几个选择:
C::fn或B::fn.然后,仍然覆盖的那个A::fn具有最终的覆盖.A::fn藏汉为fn中C和B.例如,以下结果导致编译时错误:
#include <iostream>
class A {
public:
virtual void fn() { }
};
class B : public virtual A {
public:
virtual void fn() { }
};
class C : public virtual A {
public:
virtual void fn() { }
};
// does not override fn!!
class D : public B, public C {
public:
virtual void doit() {
B::fn();
C::fn();
}
};
int main(int argc, char **argv) {
D d;
d.doit();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
但是,您可以从C和B中的A派生非虚拟,但之后您不再有钻石继承.也就是说,A中的每个数据成员在B和C中出现两次,因为在D对象中有两个A基类子对象.我建议你重新考虑一下这个设计.尝试消除需要虚拟继承的双重对象.它经常导致这种冲突的情况.
与此非常类似的情况是您想要覆盖特定功能.想象一下,你有一个在B和C中具有相同名称的虚函数(现在没有公共基数A).在D中,您希望覆盖每个函数,但为每个函数赋予不同的行为.根据您是使用B指针还是C指针调用该函数,您具有不同的行为.Herb Sutter的多重继承第三部分描述了一种很好的方法.它可能会帮助您决定您的设计.
第一个问题,是的,B和C可以定义fn()为虚函数。其次,D 当然可以B::fn()通过C::fn()使用作用域运算符 :: 第三个问题:D 必须至少知道 B 和 C,因为您必须在继承列表中定义它们。可以使用模板让B和C的类型开放:
class A
{
public:
virtual ~A() {}
virtual void fn() = 0;
};
class B: public A
{
public:
virtual ~B() {}
virtual void fn(){ std::cout << "B::fn()" << std::endl; }
};
class C: public A
{
public:
virtual ~C() {}
virtual void fn(){ std::cout << "C::fn()" << std::endl; }
};
template <typename TypeB, typename TypeC>
class D: public TypeB, public TypeC
{
public:
void Do()
{
static_cast<TypeB*>(this)->fn();
static_cast<TypeC*>(this)->fn();
}
};
typedef D<B, C> DInst;
DInst d;
d.Do();
Run Code Online (Sandbox Code Playgroud)
关于自动枚举 D 继承自的所有类的所有 fn() 函数的愿望:我不确定在不诉诸 MPL 的情况下这是否可能。至少你可以用处理 3 个或更多模板参数的版本来扩展我上面的示例,但我猜类模板参数的数量有一个(内部编译器)上限。
| 归档时间: |
|
| 查看次数: |
26028 次 |
| 最近记录: |