c++ - 我将如何制作这个非常复杂的继承树

标签 c++ inheritance

好的。所以我的情况是我有一个非常复杂的继承树,(我发誓这是合法的)。我不打算详细介绍这些类包含的内容,因为这与我的问题无关。

      A<-D
     /|  |
    / |  |
   B  |  |
    \ |  |
     \|  |
      C  |
       \ |
        \|
         E

至此继承如下。

class A 
{
    int data;
    ...
};

class B: public A {...};
class C: public A, public B {...};

我希望 C 有两次 A 的实例,所以我不使用虚拟继承。但是,我希望 E 类只继承 C::B::A::dataC::A::data 而不是 D::A::数据。我知道我必须以某种方式实现虚拟继承,但我不确定如何实现。

最佳答案

如果你环顾四周,你会发现一些关于虚拟继承的详细讨论,特别是当你结合虚拟继承和普通继承时会发生什么。

我有一些代码,我认为它创建了您所描述的层次结构,但请注意:它不会在 OS X 上链接。它编译得很好,但我得到了一些非常不寻常的 undefined symbol 。

要注意的主要事情是,当您混合使用虚拟继承和非虚拟继承时,很难获得某些基类。为了解决这个问题,我在需要虚拟继承的地方添加了另一层。然后该层可以提供唯一命名的访问器。这是通过 Virtualize 模板完成的。

我很想知道这是否会混淆其他编译器:

#include <cstdio>

template<class OnType,class UniqueType>
class Virtualize : public virtual OnType
{
public:
    inline OnType &resolve() { return *this; }
};

class A
{
public:
    A(int data): m_aData((data << 4) | 0x0A)
    {
        printf("Constructed A(%X)\n",m_aData);
    }

    A();

    virtual ~A()
    {
        printf("Destructing A(%X)\n",m_aData);
    }

    int m_aData;
};

class B: public A
{
public:
    B(int data): m_bData((data<<4) | 0x0B),
                 A((data<<4) | 0x0B)
    {
        printf("Constructed B(%X)\n",m_bData);
    }

    virtual ~B()
    {
        printf("Destructing B(%X)\n",m_bData);
    }

    A &getBsA() { return *this; }
    int m_bData;
};

class C: public Virtualize<A,C>,
         public B
{
public:
    C(int data): A((data<<4) | 0x0C),
                 B((data<<4) | 0x0C),
                 m_cData((data<<4) | 0x0C)
    {
        printf("Constructed C(%X)\n",m_cData);
    }

    virtual ~C()
    {
        printf("Destructing C(%X)\n",m_cData);
    }

    A &getCsA() { return Virtualize<A,C>::resolve(); }

    int m_cData;
};

class D: public Virtualize<A,D>
{
public:
    D(int data): m_dData((data<<4) | 0x0D),
                 A((data<<4) | 0x0D)
    {
        printf("Constructed D(%X)\n",data);
    }

    virtual ~D()
    {
        printf("Constructed D(%X)\n",m_dData);
    }

    A &getDsA() { return Virtualize<A,D>::resolve(); }

    int m_dData;
};

class E: public C, public D, public Virtualize<A,E>
{
public:
    E(int data): A((data<<4) | 0x0E),
                 C((data<<4) | 0x0E),
                 D((data<<4) | 0x0E),
                 m_eData((data<<4) | 0x0E)
    {
        printf("Constructed E(%X)\n",m_eData);
    }

    virtual ~E()
    {
        printf("Destructing E(%X)\n",m_eData);
    }

    A &getEsA() { return Virtualize<A,E>::resolve(); }

    int m_eData;
};

int main( int argc, char **argv )
{
    E e(0);

    printf("E::B::A::m_aData = %X\n",e.getBsA().m_aData);
    printf("E::C::A::m_aData = %X\n",e.getCsA().m_aData);
    printf("E::D::A::m_aData = %X\n",e.getDsA().m_aData);
    printf("E::E::A::m_aData = %X\n",e.getEsA().m_aData);

    C c(0);

    printf("C::B::A::m_aData = %X\n",c.getBsA().m_aData);
    printf("C::A::m_aData = %X\n",c.getCsA().m_aData);

    return 0;
}

对于感兴趣的人,我在链接阶段遇到了这些问题:

Undefined symbols for architecture x86_64:
  "std::terminate()", referenced from:
      _main in cc6nOq3n.o
      D::~D()    in cc6nOq3n.o
      D::~D()    in cc6nOq3n.o
      D::D(int)  in cc6nOq3n.o
      B::~B()    in cc6nOq3n.o
      B::~B()    in cc6nOq3n.o
      B::~B()    in cc6nOq3n.o
      ...
  "vtable for __cxxabiv1::__class_type_info", referenced from:
      typeinfo for Ain cc6nOq3n.o
  NOTE: a missing vtable usually means the first non-inline virtual member function has no definition.
  "vtable for __cxxabiv1::__si_class_type_info", referenced from:
      typeinfo for Din cc6nOq3n.o
      typeinfo for Bin cc6nOq3n.o
  NOTE: a missing vtable usually means the first non-inline virtual member function has no definition.
  "vtable for __cxxabiv1::__vmi_class_type_info", referenced from:
      typeinfo for Virtualize<A, E>in cc6nOq3n.o
      typeinfo for Virtualize<A, D>in cc6nOq3n.o
      typeinfo for Virtualize<A, C>in cc6nOq3n.o
      typeinfo for Cin cc6nOq3n.o
      typeinfo for Ein cc6nOq3n.o
  NOTE: a missing vtable usually means the first non-inline virtual member function has no definition.
  "operator delete(void*)", referenced from:
      A::~A()    in cc6nOq3n.o
      A::~A()    in cc6nOq3n.o
      A::~A()    in cc6nOq3n.o
      Virtualize<A, E>::~Virtualize()in cc6nOq3n.o
      Virtualize<A, E>::~Virtualize()in cc6nOq3n.o
      Virtualize<A, D>::~Virtualize()in cc6nOq3n.o
      Virtualize<A, D>::~Virtualize()in cc6nOq3n.o
      ...
  "___gxx_personality_v0", referenced from:
      Dwarf Exception Unwind Info (__eh_frame) in cc6nOq3n.o

关于c++ - 我将如何制作这个非常复杂的继承树,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17460487/

相关文章:

c++ - 只读操作的 std::map 线程安全

mysql - 列出继承? SQL 和类

c++ - 在 C++ 中沿着二维 vector (塔防)移动

c++ - 是否可以使用 C++ 在 Linux 上开发可加载内核模块(LKM)?

c++ - 如何检查 boost r-tree 中的任何 2d 点是否在给定的三角形中?

c++ - 我怎样才能防止这种在 C++ 中的转换

Java - 继承的 Fluent 方法返回类型以返回事件类的类型,而不是父类的类型

c++ - 我的老师不像其他人那样进行类型转换。有谁知道他在做什么?

Java:不能泛型 List<?扩展父> mylist

C++抽象用户界面设计