不明白以下评论(粗体)关于Bruce Eckel的“Thinking in C ++”第624卷。 1

时间:2012-01-21 23:43:34

标签: c++ constructor initializer-list

#include <fstream>
using namespace std;
ofstream out("order.out");

#define CLASS(ID) class ID { \
public: \
  ID(int) { out << #ID " constructor\n"; } \
  ~ID() { out << #ID " destructor\n"; } \
};

CLASS(Base1);
CLASS(Member1);
CLASS(Member2);
CLASS(Member3);
CLASS(Member4);

class Derived1 : public Base1 {
  Member1 m1;
  Member2 m2;
public:
  Derived1(int) : m2(1), m1(2), Base1(3) {
    out << "Derived1 constructor\n";
  }
  ~Derived1() {
    out << "Derived1 destructor\n";
  }
};

class Derived2 : public Derived1 {
  Member3 m3;
  Member4 m4;
public:
  Derived2() : m3(1), Derived1(2), m4(3) {
    out << "Derived2 constructor\n";
  }
  ~Derived2() {
    out << "Derived2 destructor\n";
  }
};

int main() {
  Derived2 d2;
}

“请注意 构造函数不是默认构造函数;他们每人都有一个int 论点。参数本身没有标识符; 唯一的原因 存在就是强迫你明确地调用构造函数 初始化列表

3 个答案:

答案 0 :(得分:1)

由于类具有用户定义的构造函数和用户定义的构造函数 构造函数不是默认构造函数,没有默认值 这些类中可用的构造函数。

这使得有必要明确提及其中一个可用的 构造函数在派生类的成员初始值设定项列表中。

class Derived : public Base {
  Derived() {} // fails to compile, no constructor Base::Base() available
  Derived() : Base(3) {} // works
};

代码的作用以及它如何实现它。我不知道 为什么你应该需要这样的东西,但你永远不会知道。

答案 1 :(得分:0)

这意味着参数没有标识符 - 没有名称 - 因此它不会在构造函数的任何地方使用。

但是,当你创建一个属于派生类的对象时,它的构造函数会调用父类的构造函数。此外,当你有一个对象成员时,你必须在构造函数中初始化它。

如果父类具有默认(无参数)构造函数,则根本不需要调用它 - 它将自动完成。此外,如果您没有初始化对象成员,它将通过默认构造函数自动完成。

由于您的类中没有一个实际上具有默认构造函数,因此您必须显式调用父类构造函数,并且还通过其唯一的现有构造函数使用一个参数初始化成员。

在所有类中使用未命名的参数就是这样 - 强制您显式调用它们的构造函数,而不是仅仅依赖于被调用的默认构造函数。

答案 2 :(得分:0)

提供带参数的构造函数可防止编译器合成默认构造函数。这会强制ID类的用户在创建此类的实例时提供被丢弃的int。我看不出这种方法的实际应用。

简化此演示代码:

#include <iostream>

struct ID
{
    ID(int)
    {
        std::cout << "ID  constructor" << std::endl;
    }
};

int main()
{
    ID this_will_compile(0);
    ID this_will_not_compile;
}

虽然第一次创建ID实例将成功,但第二次尝试将失败。编译器会告诉你类似的东西:

  

错误:没有匹配函数来调用'ID :: ID()'

从这样的类派生出来也是如此:

这会有用......

struct DerivedWorking: public ID
{
    DerivedWorking()
        :ID(0)
    {
    }
};

然而这不会,因为它没有提供intID的构造函数......

struct DerivedBroken: public ID
{
    DerivedBroken()
    {
    }
};