我了解 C++ 中的物理继承和虚拟继承。但是,我想知道这个模型是否可以通过任何设计模式或技巧来实现。
类 E 和 F 以及它们的基类不应被修改。假设它们来自外部库。
E 和 F 以下的所有内容均已打开。引入中间帮助类、非成员函数、模板……一切可以实现这一点的东西就可以了:
BaseClass
/ \
/ \
A A
/ \ / \
/ \ / \
B C B D
\ / \ /
\ / \ /
E F
\ /
\ /
\ /
FinalClass
请注意,E 和 F 不应共享 A。 FinalClass 确实应包含 2 个 A。 我的问题是,创建 E 或 F 需要 B、C 和 D 实际上继承 A。但是,如果 A 是虚拟基类,那么编译器只会在 FinalClass 中创建一个 A 对象,而不是两个不同的 A 对象。的。
所以,我认为你们中的许多人会在这里推荐组合而不是继承。然而,这里的组合建模的是“有一个”关系,而不是“是一个”关系。 在解释中,我希望 FinalClass 真正表现得像 E 或 F,包括能够将其转换为这些类。
最佳答案
即使有额外的帮助类,这种布局在 C++ 中也是不可行的。
事实上,B 继承自 A,并且您希望一侧与 C 共享 A 继承,另一侧与 D 共享,则要求 B、C 和 D 虚拟地继承 A。但随后 A 将被共享穿过钻石的两个分支。
替代方案
还有哪些替代方案?
如果你能设法打破菱形左右分支之间 A 的共享,那么你也将打破公共(public)碱基的共享。
如果您要引入一些中间类 A1、A2 来在分支中实现左右共享,那么您可能会陷入这样一个事实:两个 B 都必须继承其中一个或另一个
唯一的出路可能是为 B 创建一个重复的类。
最后一个解决方案不能满足您的要求,但如下所示:
struct Base { int x; };
struct A : public virtual Base { int a; };
struct AC : public A{}; // synonym
struct B : public virtual A { int b; };
struct BC : public virtual AC { int b; }; // !! clone !!
struct C : public virtual AC { int c; };
struct D : public virtual A { int d; };
struct E : public BC, C { int e; };
struct F : public B, D { int f; };
struct Final : public E, F { };
这里是对成员的访问:
Final f;
f.x = 2; // unambiguous: there's onely one of it
f.f = 1;
f.e = 2;
f.d = 3;
f.c = 4;
//f.b = 5; // ambiguous: there are two of it
f.E::b = 5; // successful desambiguation
f.F::b = 6; // successfuldesambiguation
//f.a = 7; // ambiguous: there are two of it
f.E::a = 7; // successful desambiguation
f.F::a = 8; // successful desambiguation
回到你的问题陈述:你说你不能干预 E 和 F 以上。在这种情况下,你的选择非常有限:
- 您公开继承
- 您通过一些中间类私有(private)继承
但是共享的效果是相同的,如以下代码所示(在上面代码的顶部):
class FI : private F // make F private
{ public:
void set_xa(int u, int v) { x = u; a= v; }
void show_xa() { cout << "x:" << x << " a:" << a << endl; }
};
class EI : private E // make E private
{
public:
void set_xa(int u, int v) { x = u; a = v; }
void show_xa() { cout << "x:" << x << " a:" << a << endl; }
};
struct Final3 : public EI, public FI { };
Final3 h;
h.EI::set_xa(3, 4);
h.FI::set_xa(5, 6);
h.EI::show_xa();
h.FI::show_xa();
// the shared virtually inherited memebers are still shared !
结论:
通过继承,您将完全受到 E 和 F 之上的设计的约束,您不能影响这些设计。
所以第一个问题是:
- 你到底不能改变这个设计(即克隆一个 B)吗?
- 将 A 放在两个分支之间难道不是 Not Acceptable 吗(也许毕竟有正当理由)?
如果你对这两个问题的回答都是“否”,那么你就必须进行组合,并实现一种 proxy design pattern ,其中您的组合对象是两个组件的代理。
关于c++ - 限制 C++ 中虚拟基类的对象共享,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29863672/