【问题标题】:Using a different base constructor for a derived class C++为派生类 C++ 使用不同的基本构造函数
【发布时间】:2011-08-15 03:03:55
【问题描述】:

据我了解,以下代码将按此顺序执行:

  1. 调用派生构造函数。
  2. 基础对象是使用默认基础构造函数构造的。
  3. 派生构造函数的主体执行。

如果是这样,成员z不是被赋值两次了吗?

class base {
public:
    int x, y, z;
    base() {x = 0; y = 0; z = 0;};
};

class derived : public base {
public:
    derived() {z = 5;};
};

是否有一种更有效的方法来创建“派生”类的对象,因此它使用不同的构造函数,在这种情况下,它只会为成员 x 和 y 分配一个值,而让 z 在派生( )?

【问题讨论】:

    标签: c++ inheritance constructor


    【解决方案1】:

    是的,有一种更有效的方法,但需要更多的代码(从而增加了维护开销)。

    class base {
    public:
        int x, y, z;
        // Default constructor
        base() {x = 0; y = 0; z = 0;};
        // Constructor to be called if you want to override the z value
        base(int zValue) { x=0; y=0; z=zValue; };
    };
    
    class derived : public base {
    public:
        derived() : base(5) {};
    };
    

    【讨论】:

      【解决方案2】:

      是的,z 在您的示例中分配了两次,就像它的样子。

      要做你想做的事,你可以做这样的事情,这需要几乎完全相同数量的代码(只是在这里和那里移动一些):

      class base {
      public:
          int x, y, z;
          base(int z = 0) : x(), y(), z(z) { }
      };
      
      class derived : public base {
      public:
          derived() : base(5) { } // with this one, z is assigned 5 once
          // or
          derived() { } // z is assigned 0 once
      };
      

      【讨论】:

        【解决方案3】:

        当然。使用所谓的ctor-initializer

        class base {
        public:
            int x, y, z;
            base(int z = 0) : x(0), y(0), z(z) {};
        };
        
        class derived : public base {
        public:
            derived() : base(5) {}
        };
        

        构造函数声明中: 之后和第一个{ 之前的代码是ctor-initializer。 (有人称其为“初始化列表”,但ctor-initializer 是 C++ 标准所称的。)

        您应该始终使用ctor-initializers 将类成员初始化为某个值。虽然对于ints 并不重要,但使用ctor-initializers 进行初始化可能比默认构造类成员然后赋值要快。

        【讨论】:

          【解决方案4】:

          当然,你可以做到。

          使用 member-initialization-list 作为:

          class base {
          public:
              int x, y, z;
              base(int a, int b, int c) : x(a), y(b), z(c) {}
                                     //^^^^^^^^^^^^^^^^^^^ it's member-initialization-list!
          
          };
          
          class derived : public base {
          public:
              derived() : base(0,0,5) {}
                      // ^^^^^^^^^^^ call the specific base constructor
          };
          

          【讨论】:

            【解决方案5】:

            详细说明 Andrew 的答案,如果您真的想确保 所有 base 的成员仅设置一次,并且以最有效的方式,您可以使用成员-list 初始化器,而不是在构造函数中设置值。

            class base {
            public:
                int x, y, z;
                base() : x(0), y(0), z(0) {};
                base( int xval, int yval, int zval ) : 
                        x(xval), y(yval), z(zval) 
                        { };
            };
            
            class derived : public base {
            public:
                derived() : base( 0, 0, 5 ) {};
            };
            

            大多数编译器会为 : x(_x), ... 生成与在构造函数中设置值相同的代码,但我见过一些没有。

            【讨论】:

              猜你喜欢
              • 2015-08-18
              • 1970-01-01
              • 2021-02-14
              • 2016-07-19
              • 2018-07-21
              • 2014-11-27
              • 2020-11-28
              • 1970-01-01
              相关资源
              最近更新 更多