【问题标题】:Does the code get copied to derived class?代码是否被复制到派生类?
【发布时间】:2015-01-03 01:38:45
【问题描述】:

每当我从基类派生一个新类时说:

#include <iostream>

class A {

protected:
     int f;

public:

    void get() {
        std::cout << "The address is: "
        << &f << std::endl;
        }
};

class B : public A {
        // ....
};

int main() {

     A a;
     a.get();

     B b;
     b.get();

     return 0;
}

地址是:0xbfb0d5b8
地址为:0xbfb0d5bc

这是否意味着class A 中的所有代码都将复制到class B?由于我在 B 类中什么都没有,即没有数据成员或函数所以,当我创建 B 类的一个实例时,我发现它在不同的地址有自己的变量,它也有一个成员函数。不复制怎么会有自己的复制成员呢?

这就是我们所说的代码重用在继承中的意思吗?

编辑:

更新了我的代码以反映我所说的复制变量的含义。

【问题讨论】:

  • 如果你问编译后的程序是否包含两次相同的函数代码(二进制形式):否。
  • 更好的表达方式是A类中的代码也被B类使用。但是没有发生复制,它们使用相同的代码副本。
  • @user963241:您没有将任何东西声明为静态,每个类的每个实例都会使用不同的变量...
  • @user963241 class 不包含成员,它的实例包含。每个实例都有自己的成员变量。类定义就像一个实例的蓝图。
  • 在你的例子中,试试A a1; a1.get(); A a2; a2.get();

标签: c++ inheritance code-reuse


【解决方案1】:

在继承期间永远不会复制代码。但是在运行时创建或实例化子对象(B 类)时,它会继承父类/对象(A 类)的功能和属性。

【讨论】:

    【解决方案2】:

    A 类的代码不会复制到 B 类,因为只有一个地方编写了代码。

    然而,这里是可重用部分,当使用类 bu 时,可以调用方法并使用成员,相对于privatepublic、等,因此不必为两个类编写相同的代码做同样的事情

    例如,如果我有一个圆形和一个方形,并且它们都有一个名为 color 的成员,我想要一个更改它的方法,我不需要编写方法和成员两次,但让它们继承类 Shape这将实现一次,然后他们都将能够使用该方法,从而在两个地方重用一个方法

    【讨论】:

      【解决方案3】:

      我不确定“复制”是正确的词(编译器只会编译class A 中的代码一次)。由于您使用了公共继承,class B 实际上class A 的一种特殊类型。因此,class B 确实可以访问class A 的每个(非私有)成员,因此代码被重复使用。

      另外,来自cmets中的对话:

      没有。没有什么是“复制”的,A 和 B 的每个实例都有自己的变量值,除了任何静态数据成员。对于静态数据成员,同样不会进行复制;只有一个变量,由AB 的所有实例共享。

      【讨论】:

        【解决方案4】:

        在您的示例中,您正在比较两个不同类的两个不同实例。不同的实例意味着不同的基地址来存储实例数据。

        也许一个类的字段是否在派生类中被复制的更好测试如下:

        #include <iostream>
        
        class A {
        
        protected:
         int f;
        
        public:
        
        void get() {
            std::cout << "The address is: " << &f << std::endl;
            }
        };
        
        class B : public A {
            // ....
        };
        
        int main() {
        
         B b;
         b.get();
        
         A *a = &b;
         a->get();
        
         return 0;
        }
        

        输出是:

        The address is: 0x7fff41d523f0
        The address is: 0x7fff41d523f0
        

        通过该程序,我们可以看到即使我们有一个类B 的实例,它的继承内容在物理上与原始类A 中的相同。请注意,也可以在派生类中重新定义类成员,但如果我们将派生类的实例强制为父类(就像我在示例中所做的那样),原始成员仍然可用。

        【讨论】:

          【解决方案5】:

          C++ 语言标准的§1.8(2) 定义了子对象的含义:

          对象可以包含其他对象,称为子对象。子对象可以是成员子对象 (9.2)、基类子对象(第10 条)或数组元素。不是任何其他对象的子对象的对象称为完整对象

          这些是成员子对象和数组元素的示例,您应该熟悉:

          int a[5];
          a[2]; // the third array element subobject of the complete object a
          
          struct S { int x; }
          S s;
          s.x; // a member subobject of the complete object s
          

          剩下一种子对象,即您感兴趣的子对象:基类子对象。

          struct B { int x; }
          struct D : public B { int y; }
          
          D d;
          d.y; // a member subobject of the complete object d
          d.x; // a member subobject of a base class subobject of the complete object d
          
          B &b = d; // a reference to a base class subobject of the complete object d
          

          派生类的每个实例都包含其基类的一个实例,作为基类子对象。

          【讨论】:

            【解决方案6】:

            我对继承和代码重用之间的关系也有一些疑问。这是我对此的看法。

            继承是一种用于分类和促进多态性的机制。使用继承,我们可以建立在不同抽象级别的类别中分离的概念层次结构。通过这样做,我们可以有效地使用另一个 OOP 概念,即多态性,它允许相同的控制代码管理一个类别中的所有对象,即使它们的实现方式不同。

            我不认为我们将继承用于代码重用目的。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2011-10-15
              • 2011-05-04
              • 1970-01-01
              • 1970-01-01
              • 2022-10-01
              • 1970-01-01
              • 2011-11-23
              相关资源
              最近更新 更多