完全掌握C++编程中构造函数使用的超级学习教程

2020-01-06 14:26:49王冬梅

你应看到以下输出:


BaseClass1 constructor.
BaseClass2 constructor.
BaseClass3 constructor.
DerivedClass constructor.

构造函数中的虚函数
我们建议你谨慎调用构造函数中的虚函数。基类构造函数始终在派生类构造函数之前调用,因此基构造函数中调用的函数是基类版本,而非派生类版本。在下面的示例中,构造 DerivedClass 会导致执行 BaseClass 的 print_it() 实现早于 DerivedClass 构造函数导致执行 DerivedClass 的 print_it() 实现:


#include <iostream>
using namespace std;

class BaseClass{
public:
  BaseClass(){
    print_it();
  }
  virtual void print_it() {
    cout << "BaseClass print_it" << endl;
  }
};

class DerivedClass : public BaseClass {
public:
  DerivedClass() {
    print_it();
  }
  virtual void print_it(){
    cout << "Derived Class print_it" << endl;
  }
};

int main() {

  DerivedClass dc;
}

这是输出:


BaseClass print_it
Derived Class print_it

构造函数和复合类
包含类类型成员的类称为“复合类”。创建复合类的类类型成员时,调用类自己的构造函数之前,先调用构造函数。当包含的类没有默认构造函数是,必须使用复合类构造函数中的初始化列表。在之前的 StorageBox 示例中,如果将 m_label 成员变量的类型更改为新的 Label 类,则必须调用基类构造函数,并且将 m_label 变量(位于 StorageBox 构造函数中)初始化:


class Label {
public:
  Label(const string& name, const string& address) { m_name = name; m_address = address; }
  string m_name;
  string m_address;
};

class StorageBox : public Box {
public:
  StorageBox(int width, int length, int height, Label label) 
    : Box(width, length, height), m_label(label){}
private:
  Label m_label;
};

int main(){
// passing a named Label
  Label label1{ "some_name", "some_address" };
  StorageBox sb1(1, 2, 3, label1);

  // passing a temporary label
  StorageBox sb2(3, 4, 5, Label{ "another name", "another address" });

  // passing a temporary label as an initializer list
  StorageBox sb3(1, 2, 3, {"myname", "myaddress"});
}

委托构造函数
委托构造函数调用同一类中的其他构造函数,完成部分初始化工作。在下面的示例中,派生类具有三个构造函数,第二个构造函数委托第一个,第三个构造函数委托第二个:


#include <iostream>
using namespace std;

class ConstructorDestructor {
public:
  ConstructorDestructor() {
    cout << "ConstructorDestructor default constructor." << endl;
  }
  ConstructorDestructor(int int1) {
    cout << "ConstructorDestructor constructor with 1 int." << endl;
  }
  ConstructorDestructor(int int1, int int2) : ConstructorDestructor(int1) {
    cout << "ConstructorDestructor constructor with 2 ints." << endl;

    throw exception();
  }
  ConstructorDestructor(int int1, int int2, int int3) : ConstructorDestructor(int1, int2) {
    cout << "ConstructorDestructor constructor with 3 ints." << endl;
  }
  ~ConstructorDestructor() {
    cout << "ConstructorDestructor destructor." << endl;
  }
};

int main() {
  ConstructorDestructor dc(1, 2, 3);
}