使用初始化列表和超类构造函数声明子类构造函数的正确方法

Proper way of declaring subclass constructer with both initialization lists and superclass constructor

我目前的情况如下。这是一个或多或少简单的继承案例,我对此有很多疑问。

我有一个带有两个变量 foo_bar_ 的抽象 class(=它有纯虚函数)。 foo_ 由构造函数中的参数设置。 bar_ 大多数子 class 应该默认为 1000,但我想要一个特定的 class 将其覆盖为 50000。

这是一个代码片段:

class Base {
 protected:
  const int foo_;
  const int bar_;
 public:
  Base(int foo) : foo_{foo}, bar_{1000} {}
}

class Derived : public Base {}

首先,一个简单的问题:是像我在示例中那样在初始化列表中初始化 bar_ 还是在变量声明为 const int bar_{1000}; 的顶部进行初始化更好?

第二个快速问题:可以在初始化列表中使用 {} 还是应该使用 ()

如何正确编写 Derived class 的构造函数?我想专门调用我为 Base 定义的构造函数,还使用初始化列表将 bar_ 设置为 50000.

我的想法是这样的:

Derived(int foo) : Base(foo), bar_{50000} {}

编辑: 经过一番尝试后,我注意到在 Derived 的构造函数列表中修改 bar_ 显然是不可能的,因为 "bar_" is not a nonstatic data member or base class of class "Derived".

Is it better practice to initialize bar_ in the initialization list as I did in the example or do it at the top where the variable was declared as const int bar_{1000};?

这与其说是关于 "best pratice",不如说是关于 "what do you want"? 1000 是构造函数中的初始化程序获取 "overriden" 的默认初始值。您可以有默认初始化器,例如,一个构造器使用不同的初始化器,另一个构造器不使用。

How do I correctly write the constructor for the Derived class?

您可以编写一个允许您传递两个值的受保护构造函数:

class Base {
 protected:
  const int foo_;
  const int bar_;
  Base(int foo, int bar) : foo_(foo), bar_(bar) {}
 public:
  Base(int foo) : foo_{foo}, bar_{1000} {}
};

class Derived : public Base {
    public:
    Derived(int foo) : Base(foo,5000) {}
};

这个问题有很多方面需要解决。

我对初始化的偏好是:

class Base {
 protected:
  const int foo_{};
  const int bar_{1000};
 public:
  Base(int foo) : foo_{foo} {}
}

我喜欢这个的原因是因为 class 可以有多个构造函数。这样可以更轻松地维护默认值。

关于初始化的问题,我放弃了。只需使用现有的样式指南即可。 (目前他们似乎在到处使用 {} 上标准化)在构造函数之外,它的初始化更加混乱,如果你想被细节吓到,我可以推荐:Nicolai Josuttis "The Nightmare of Initialization in C++".

为了在派生 class 中编写构造函数,我认为您的成员不应受到保护。如果它是私有的,唯一的写法是:

class Base {
 private:
  const int foo_{};
  const int bar_{1'000};
 protected:
  Base(int foo, int bar) : foo_{foo}, bar_{bar} {}
 public:
  Base(int foo) : foo_{foo} {}
}

class Derived : public Base {
public:
    Derived(int foo) : Base{foo, 50'000} {}
}

有了这个,我将通过受保护的方法公开对它们的访问。即使忽略该建议,我也会使用这种技术来初始化它,因为如果您只查看 'Base' class.

,这是最容易理解会发生什么的方法