【问题标题】:Inheritance vs Composition:: Is my understanding correct?继承与组合:: 我的理解正确吗?
【发布时间】:2015-04-03 06:55:46
【问题描述】:

在组合中,一个类明确包含另一个类。但是在继承中,基类隐式包含在派生类中。正确与否?我问这个是因为经过几天的继承研究,直到今天我才在某个地方读到派生类的对象总是包含它的基类的对象。

我的意思是,我以为只有一个对象,只是功能会被继承,但我不知道它还会包含一个基类的对象。

【问题讨论】:

  • 您是在询问基类对象是隐式包含还是显式包含?还是你问它是否被包含在内?

标签: c++


【解决方案1】:

在合成中,一个对象包含另一个对象。在继承中,您的对象是获取基类的属性。

我的意思是,我认为只有一个对象,只有一个 功能将被继承,但我不知道它也会 包含一个基类的对象。

是的,你是对的,只有一个对象并且功能正在被继承。即使您的基类有成员变量,也会将大小添加到您的对象大小中。

您可以直接调用基类的公共和保护方法。在共同容器中,您只能访问公共方法。

【讨论】:

  • 由于这是 c++,可能值得一提的是极端情况,即对象的大小不能为 0,但从空结构继承可能不会增加对象的大小。
【解决方案2】:

应该是: 在组合中,一个类显式包含另一个类的一个对象。但是在继承中,基类隐含在派生类中。

简而言之: 组合是关于类和对象的关系。 继承是关于类和类的关系。

请记住“优先组合而不是继承”。 Prefer composition over inheritance?

【讨论】:

    【解决方案3】:

    一般派生类包含所有数据成员并共享基类的属性/方法,但组合和继承之间存在差异。

    “组合”是指一个对象“拥有”另一个对象。例如:人类有肝脏。在类设计中可以如下所示:

    class Liver {};
    
    class Human
    {
    public:
      Human() {}
    private:
      Liver mLiver;
    }
    

    当谈到继承时,有两种选择:公共继承大致说一个对象“是”另一种对象。例如:人是一种生物。说人类里面“有”一个活的生物听起来并不自然。在这种情况下,公共继承是一种可行的方法:

    class LivingCreature {};
    
    class Human : public LivingCreature
    {
    public:
      Human() {}
    }
    

    其他选项是受保护/私有继承,它应该用于“根据”其他对象来实现某些对象。一般来说,它也可以被视为一种组合,但通常第一种方法更好。

    总结:

    • 如果您可以说一个对象“是”另一种更通用的对象:公共继承是最好的选择,
    • 如果您可以说一个对象“拥有”另一个对象:使用组合。

    【讨论】:

      【解决方案4】:

      考虑代码:

      class Engine
      {
      //Some Code
      };
      
      class Vehicle
      {
      //Some Code
      };
      
      class Car:Vehicle
      {
          Engine engine;
          //Some Code
      };
      

      在这种情况下,Car 类继承了 Vehicle 类。 Car 类的对象不包含对象 Vehicle,而是 Vehicle 类的对象(继承)。另一方面,它确实包含类 Engine(Composition) 的对象。

      您可以使用this 访问父函数的事实是因为 Car 对象是 Vehicle 而不是因为它包含 Vehicle 对象。

      【讨论】:

        【解决方案5】:

        在组合中,一个类明确包含另一个类。但是在继承中,基类隐式包含在派生类中。正确与否?

        这完全是知识/观点的问题:如果您知道继承意味着基类实例将嵌入派生类中,那么说 class Dervived : Base 可以视为明确要求,而如果您知道在class X 中定义一个变量意味着它是一个成员变量,将包含在X 的实例中,那么这也可以看作是显式的。

        我问这个是因为在研究了几天继承之后,直到今天我才在某个地方读到派生类的对象总是包含它的 [原文如此] 基类的对象。

        实际包含基类对象与通过一些更未指定/神秘的手段有时可以替代基类实例之间的区别,在开始学习继承时不一定是最重要的事情,因此很容易想象一下,并不是所有的学习材料都强调它。

        我的意思是,我以为只有一个对象,只是功能会被继承,但我不知道它还会包含一个基类的对象。

        在实现级别,它实际上包含一个基类实例很重要,因此为处理基类对象而编译的代码可以在派生类实例上同样出色地工作。 C++ 标准可能认为它只是具有相同二进制布局的基类内容的嵌入副本,而不是实际的基类对象,但随后必须将标准中的大量文本添加到提到派生对象可用于可接受基类实例的场景。换句话说,这种区别有点武断,但如果它既直观又自然地适用于更简单、更简洁的标准措辞,对每个人来说都会更容易。

        【讨论】:

          【解决方案6】:

          继承 vs 组合:: 我的理解正确吗?

          概念差异:

          继承:

          在继承的情况下,派生类基类的子类型。 这意味着如果您从Animal 派生Dog,那么Dog Animal 和 可以在Animal 上执行的所有* 操作都可以在Dog 上执行。

          • 使用privateprotectedpublic 继承,但是,您可以控制谁知道 DogAnimal 以及谁知道Animal 的内部工作原理。在protectedprivate 继承的情况下,只有Dog 会知道它是Animal,但从外部看不会很明显。

          组成:

          在组合的情况下,一个类被包含到另一个类中。 Car 不是 Wheel。但它包含Wheel。所以在Wheel 上工作的操作不会在Car 上工作。

          通过将Wheel 类型的成员变量声明为publicprivateprotected,您可以控制谁可以访问CarWheels。

          我相信这已经足够清楚了吗?

          实现细节:

          在 C++ 的情况下,基类的成员包含在派生类中。基类中存在的方法也可以在派生类中访问 - 某处。访问说明符 privatepublicprotected AND 继承类型决定了哪些方法可见以及在哪里可见。

          我以为只有一个对象

          这是一个对象。

          在 microsoft 编译器和 g++ 中,对象被“合并”在一起,这意味着在以下情况下:

          struct Base{
              int a;
          };
          
          strict Derived: public Base{
              int b;
          };
          

          Derived 在内部可能(需要检查 C++ 标准来确定)具有这种布局。

          strict Derived{
              int a;
              int c;
          };
          

          struct Derived{
              Base _;
              int c;
          };
          

          在多重继承和菱形继承的情况下,事情会变得更加复杂,基类可以被多次包含。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2011-05-20
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2014-01-17
            • 2015-03-07
            • 1970-01-01
            相关资源
            最近更新 更多