仅用于代码重用c ++的继承

时间:2012-09-26 21:04:34

标签: c++ oop inheritance multiple-inheritance

我有A和B类。现在我需要编写一个新的C类,它将在A和B中使用一些字段和方法,但不是全部。 (我将使用A和B中大约50%的东西)。

现在我正在考虑从A和B继承。但这将使C包含许多没有意义的字段和方法。

基本上我只是为了代码重用而使用继承,否则我将不得不从A和B复制并粘贴多行代码。

这种做法真的很糟糕吗?有不同的方法吗?

谢谢!

5 个答案:

答案 0 :(得分:6)

继承没有“是一半”的概念,所以它绝对不是去这里的方式。听起来这是构图的主要案例。

听起来AB有多个“功能”,因为每个功能中有一半足以组成C

我不确定这是否适用于您的情况,但考虑将A分为两部分,A1A2以及C中所需的A1功能。然后对B B1B2进行同样的操作。

A将由A1A2组成,B将由B1B2和{{组成1}}将是CA1的组合。没有任何必要的功能或数据。

答案 1 :(得分:3)

继承应该使用“是一种”范式 这意味着C应该从A,B继承,如果它是A和B的那种 如果你已经在使用多重继承,你可能想要将A和B分解为多个类,每个类处理一小段代码,然后只从你需要的东西继承C - 这样C只会占用它的空间需求(假设A和B有很多成员) 请记住,类的大小不受成员方法的影响,只受成员数据的影响。

答案 2 :(得分:3)

正如Herb Sutter和Andrei Alexandrescu在他们的书 C++ Coding Standards (item 34) 中解释的那样,继承是C ++允许您在两个类之间使用的最紧密的关系之一 - 它仅次于{ {1}}类之间的关系。

根据S.O.L.I.D principles of OO,成功的设计应该针对类之间的松散耦合 - 这可以将依赖性保持在最低限度;这反过来又暗示继承是一种应该谨慎使用的工具。

当然,依赖关系通常需要存在某处,因此合理的折衷方案可以从没有实现的类继承(类似于所谓的friend s语言,如C#和Java)。 e.g。

interface

使用这种方法,如果您在多个 Drivable 类之间重用了代码元素,则通常会使用合成或其他较弱的关系来消除重复的代码。
例如也许你想要为class IDriveable { public: virtual void GoForward() = 0; virtual void GoBackward() = 0; }; class Car : public IDriveable { /* etc. */ }; class Bus : public IDriveable { /* etc. */ }; class Train : public IDriveable { /* etc. */ }; TurnLeft而不是Bus重复使用Car代码而左转是不合逻辑的,因此Train可能最终会一个单独的类,它是TurnLeftBus的成员。

  • 此外,任何可能需要了解所有与模糊相关的类的功能都是类heirarchy的外部,只知道接口/基础而不是细节实现细节。

最终结果可能是构成的少量额外代码,但通常是不太复杂的设计,通常是更容易管理的代码。设计这样的代码没有任何硬性规则,因为它完全取决于你试图解决的独特问题。

还有其他方法可以在没有紧密耦合的情况下重用代码 - 模板允许您隐式定义接口而不包含包含纯Car函数的空类(模板提供额外的类型安全性 - 这是一个非常良好事情,但它们在语法上有点复杂);

还有一些方法可以使用virtual和lambdas来重用更实用的代码 - 再次传递函数对象时通常不会涉及严格的依赖关系。

答案 3 :(得分:2)

很糟糕。只有在逻辑上有意义时才使用继承。

使用组合代替(private继承是一种组合形式,但最好是老派):

class C
{
    A a;
    B b;
}

如果C不是由AB组成,您也可以改为使用指针,因此C的大小不会增加。

答案 4 :(得分:0)

听起来您可以从重构代码中受益:

而不是:

class A
{
  virtual void foo();
  virtual void bar();
};

class B
{
  virtual void biz();
  virtual void baz();
};

class C : public A, public B
{
  virtual void foo() { /* my stuff */ }
  virtual void biz() { /* my other stuff */ +

  // but I don't need bar or baz!
};

考虑在C中分割出你想要的A和B的概念上不同的部分:

class core_A
{
  virtual void foo();
};

class A : public core_A
{
  virtual void bar();
};

class core_B
{
  virtual void biz();
};

class B : public core_B
{
  virtual void baz();
};

class C : public core_A, public core_B
{
  virtual void foo() { /* my stuff */ }
  virtual void biz() { /* my other stuff */ +

  // Great, I don't have bar or baz!
};