钻石形状的多重继承,仅具有函数

时间:2016-02-25 13:44:24

标签: c++ inheritance

我想讨论c ++中的继承问题。 基本思想是拥有一个带有属性的基类和具有此属性访问器的不同子类。并且在底部应该是一个类,它将子类合并为一个类。它是钻石形状,引入了一些问题。

class A {
public:
  A() { prop = 1; }
  int prop;
};

class B : public A {
public:
  int getProp() { return prop; }
private:
  B();
};

class C : public A {
public:
  int setProp(int v) { prop = v; }
private:
  C();
};

class D : public B, public C {
private:
  D();
};

usage() {
  A* a = new A();
  B* b = (B*)a; // Works
  b->getProp(); // Works
  D* d = (D*)a; // This fails, because of diamond inheritance
  d->setProp(5);// This is kindof the goal
  d->getProp();// This is kindof the goal
}

所以,我已经阅读了一些关于虚拟继承的内容,但是我无法实现对D的转换,这应该包括B和A的所有方法。也许我在那里遗漏了一些东西。

另一方面。我真的只有B和C类中的函数,所以通常可以通过静态包装器获取类的实例来实现这些访问器。但是我想问你想要在没有任何包装器的情况下实现它的想法,它将原来的A作为参数。

编辑1: 我将为您提供一些方案来阐明我想要实现的目标。 想象一下项目A,B,C,D和E

Project_A contains Class_A. This class contains some member variables.
P_A also creates 5 instances of the class.
Project_C contains Class_C.
P_C also asks P_A to get the 5 instances of C_A.
P_C sets the properties of the 5 instances via its accessors.
Project_B contains Class B.
P_B asks P_A to get the 5 instances of C_A.
P_B gets the properties of the 5 instances.
Project_D contains Class D.
P_D does set and get the properties via the accessors of C_B and C_C.
Project_E contains Class E.
Project_E works on a different property of A.

P_B knows P_A
P_C knows P_A
P_D knows P_A, P_B, P_C
P_E knows P_A

这些项目由不同方面处理。

也许这有帮助。也许它没有。让我们来看看。

编辑2: 这里是另一个伪代码示例。也许这样对你来说更有意义。关键可能是,A不知道它拥有哪些属性。 (或者更确切地说,他们的意思)

class A {
    map<int, int> props;
}

class B : private A {
    getProp1() { return props(1)}
    setProp1(int prop) { props(1) = prop }
}

class C : private A {
    getProp2() { return props(2)}
    setProp2(int prop) { props(2) = prop }
}

class D : public B, public C {
  // This is just a combination of B and C for comfort.
}

class E : private A {
    getProp3() { return props(3)}
    setProp3(int prop) { props(3) = prop }
}

2 个答案:

答案 0 :(得分:1)

B和C必须从A

虚拟继承
class A {
public:
  A() { prop = 1; }
  int prop;
};

class B : virtual public A {
public:
  int getProp() { return prop; }
private:
  B();
};

class C : virtual public A {
public:
  int setProp(int v) { prop = v; }
private:
  C();
};

class D : public B, public C {
private:
  D();
};

usage() {
  A* a = new D(); //!!!! NEW D here
  B* b = dynamic_cast<B*>(a); // 
  b->getProp(); // 
  D* d = dynamic_cast<D*>(a); // Not diamond inheritance in cause, bad init of a!
  d->setProp(5);// 
  d->getProp();//
}

另外,使用C ++强制转换(dynamic_cast,static_cast,...)。如果您使用它,当您尝试将A* a=new A()转换为B 时,将返回nullptr,您应该测试dynamic_cast 的结果。通过引用,dynamic_cast抛出异常。 A实例可以是B实例。但DBC实例可以是A实例。 D也可以是CD个实例。

答案 1 :(得分:0)

所以,很明显没有人关心了。所以这是我想要规避的解决方案。

class A {
public:
  map<string, string> keyvalue;
}
class B {
  static string getProp1(A* a) { return a->keyvalue.find("prop_1")->second;}
}

class C {
  static string getProp2(A* a) { return a->keyvalue.find("prop_2")->second;}
}

class BandC : public B, public C {
  //THis is just a combination of B and C
}

由于B和C类只包含函数,因此逻辑上不需要它们的实例。它们基本上可以在A类实例上运行。

如果不清楚。如果我从A继承B和C并在BandC中再次组合它,我会因菱形而得到错误。