c++ - 限制 C++ 中虚拟基类的对象共享

标签 c++ inheritance multiple-inheritance modeling virtual-inheritance

我了解 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/

相关文章:

inheritance - 如何在 React 组件和 es6 类中使用继承

inheritance - 域到域的继承

c++ - 将派生类存储到 vector C++

c++ - 添加静态 constexpr 成员会改变结构/类的内存映射吗?

c++ - ostream,复制函数打印字符串地址,而不是字符串内容

c++ - "unspecialized class template can' t be used as a template argument”是什么意思?

c++ - 不明确的类型引用

oop - 为什么大多数编程语言不支持多重继承?

c++ - 派生类中指向基类的指针 vector

C++删除指针