情况是这样的:
class A
{
public:
A();
void actionA();
private:
int a;
};
class B1
: public A
{
...
};
class B2
: public A
{
...
};
class OrthogonalFeature
: public A
{
void orthogonalFeature();
};
class C1
: public B1
, public OrthogonalFeature
{
...
};
class C2
: public B2
, public OrthogonalFeature
{
...
};
class User
{
public:
void run() {
c.actionA();
c.orthogonalFeature();
}
private:
MyNeededType c; // c is either C1 or C2
};
User
类需要拥有一个可以执行actionA()
和actionB()
的对象。
因此,我可能想创建类
MyNeededType
,它需要继承于A
和(B1
或B2
),并且我遇到了钻石问题(数据成员a
不明确)。解决这个问题的常用方法是使用虚拟继承。但是,对于这个项目,出于性能原因,我不能使用虚拟继承(请仅接受表面值)。
所以我有一个问题。可能有帮助的是
User
类只能在我拥有的 2 个现有类上运行:C1
和 C2
。所以我想到的另一个选择是让C1
和C2
继承A
,并在这些派生类中重新实现orthogonalFeature
,而不是继承OrthogonalFeature
。因此没有钻石。看起来是这样的:
class C1
: public B1
{
public:
void orthogonalFeature();
};
class C2
: public B2
{
void orthogonalFeature();
};
我喜欢这个解决方案,但是如何在
c
中指定 User
的类型?我觉得我需要创建一个类型,这意味着:这个类是C1
或C2
。但我不知道c++中存在这个?
欢迎任何想法,谢谢!
快速访问 A 数据成员对您来说有多重要?最终,虚拟继承使您可以轻松访问 A::a,但要付出一定的代价才能访问 B2 和 B1 中的几乎所有其他内容。
不使用钻石,分享A::a能达到你想要的效果吗?在COM模型中,所有接口类都使用从IUnknown接口继承的简单继承,但是实例化类必须实现最终的“真正的基类”函数才能获得“注册的”IUnknown。当然,该模型中没有数据成员。
您可以简单地设置
B1: public trueA
和 B2: public indirectA
,然后在您的实现中,有一个模板包装器“激活”indirectA 以找到 trueA。实际上,您还可以让您的实现包装器从 trueA、B1、B2 派生,并将indirectA 的 B1 和 B2 实例修复到它吗?
但请注意,这依赖于 B1 和 B2 的构造函数不引用 A,因为它尚未初始化。
可以肮脏地破解indirectA的构造函数以“知道”它实际上是在C:B2中实例化的,并推断出C:B1:A或C:A,并且您可以通过使用模板来推动定义来获得相当干净的结果,也许还有一点 CRTP?
我想说更喜欢通过设计组合而不是多重继承来解决钻石问题。