没有数据成员的Diamond(多重继承)
Diamond (multiple inheritance) with no data members
假设我们有通常的菱形图案:
class A
{
public:
virtual char foo() = 0;
virtual ~A() {}
};
class B : public A
{
public:
virtual char foo() { return 'B';}
virtual ~B() {}
};
class C : public A
{
public:
virtual char foo() { return 'C';}
virtual ~C() {}
};
class D : public B, public C
{
public:
virtual char foo() { return 'D';}
virtual ~D() {}
};
请注意,基类A
没有任何数据成员。事实上,它只是一个具有纯虚拟方法的接口。
现在如果我这样做:
D* d = new D();
A* a = static_cast<A*>(d);
编译器会告诉我,由于有两个A基类,所以强制转换是不明确的。
但如果我这样做呢:
D* d = new D();
B* b = static_cast<B*>(d); // Or C* c = static_cast<C*>(d);
A* a = static_cast<A*>(b);
现在我有一个指向我的一个A
基类的指针,我可以执行a->foo()
。
这安全吗?
我想知道的是,我是否可以进行这种双重升级,使指针指向接口(没有数据成员(,而不需要虚拟继承的开销。无论如何,我都不打算向下转换指针,也不打算对它做任何不调用虚拟方法的事情。
我知道这意味着有两个基类,但由于没有成员,这不重要,还是重要?
EDIT
:我正在努力寻找实现接口的方法,我想我只能使用虚拟继承。
假设我有一个类Buffer
(接口类(和一个从中派生的BufferImplementation
类
现在假设我有另一个接口IOBuffer
(它派生自另一个界面Buffer
(,其中有一个IOBufferImplementation
类,它必须派生自BufferImplementation
和IOBuffer
接口。
在我前面的例子中,Buffer是A,BufferImplementation是B,IOBuffer是C,IOBufferImplemention是D。
Is this safe?
我想是的。您正在使用从派生类D
到基本A
的两条路径之一。您现在可以安全地使用接口成员。
请注意,如果A
中有纯虚拟方法而不是D
中的overridden
,则使用D->B->A
路径将始终调用B
中的overridden
方法(类似于D->C->A
路径(,尽管C
中的实现是有意的/有用的。当A
具有数据成员时,这也将起作用,并且在该特定设置中,将使用通过D->B->A
继承的数据成员。
您所写的不是菱形图案!
如果你想把这个做成菱形图案,你必须virtual inherit
!
class B : virtual public A
和
class C : virtual public A
你的版本只是从基类中线性派生,这使得D包含基类A的两倍。因此,如果你要求,编译器没有机会知道应该选择哪个A。如果你用虚拟派生,你在D中只得到一个A。
请记住,您必须手动调用D中A的构造函数。同样,如果C或D的构造函数调用A的构造函数!如果您创建了一个D!
- 关于C++中具有多重继承"this"指针的说明
- C++中模板化异常类的多重继承
- 虚拟继承中是否存在多重继承?
- 如何在 c++ 多重继承中调用父非虚函数?
- 多重继承相同的方法名,没有歧义
- 使用enable_if解决多重继承歧义
- 多重继承导致虚假的模糊虚拟函数过载
- 多重继承和访问不明确的元素
- C++ 多重继承:使用基类 A 的实现实现基类 B 的抽象方法
- 多重继承中的派生类的行为类似于聚合
- 为什么我的 Hippomock 期望在使用多重继承时失败
- 带有此指针的模板类多重继承构造函数不起作用?
- 使用多重继承时出现编译错误
- 增强多重继承的序列化
- 多重继承:跳过'virtual'关键字并拒绝菱形层次结构的使用?
- 仅函数的多重继承 - 没有虚拟和 CRTP
- C++多重继承和鸭子类型
- C++两次从文件保存对象读取多重继承
- 从多重继承中的派生类函数调用适当的父类函数
- 没有数据成员的Diamond(多重继承)