构造器概述¶
构造函数(constructor
)用于自定义如何初始化类成员,或在创建类的对象时调用函数。构造函数与类同名,没有返回值。可以根据需要定义任意多个重载构造函数,以各种方式自定义初始化。通常定义构造函数访问权限为public
,以便类定义或继承层次结构之外的代码可以创建类对象。但也可以将构造函数声明为protected
或private
- 构造器可以声明为
inline、explicit、friend
或constexpr
- 构造器可以初始化声明为
const/volatile/const volatile
的对象。这些对象在构造器完成后成为const
(举例) - 在源文件中定义构造器,给它一个与任何其他成员函数一样的限定名,比如
Box::Box(){...}
当声明类实例时,编译器根据重载解析规则(the rules of overload resolution
)选择要调用的构造函数
int main()
{
Box b; // Calls Box()
// Using uniform initialization (preferred):
Box b2 {5}; // Calls Box(int)
Box b3 {5, 8, 12}; // Calls Box(int, int, int)
// Using function-style notation:
Box b4(2, 4, 6); // Calls Box(int, int, int)
}
成员初始化列表¶
构造函数可以设置成员初始化列表(member initializer list
),在执行构造函数体之前初始化类成员,这是一种更有效的初始化类成员的方法
class Box {
public:
Box(int width, int height, int length) : m_width(width), m_height(height) {
this->m_length = length;
}
private:
int m_width;
int m_height;
int m_length;
};
注意:const
和引用类型成员必须在成员初始化列表中初始化
应该在初始值列表中调用参数化基类构造函数,以确保在执行派生构造函数之前基类已完全初始化
class Base {
public:
Base(int length) : length(length) {}
private:
const int length;
};
class Box : public Base {
public:
Box(int width, int height, int length) : Base(length), m_width(width), m_height(height) {}
private:
int m_width;
int m_height;
};
内容列表¶
下文可分为:
- 默认构造器
- 复制构造器
- 移动构造器
- 构造器执行顺序
- 构造器的继承
- 构造器和复合类
默认构造器¶
默认构造器通常指的是没有参数的构造器,或者所有参数都有默认值的构造器
如果定义类时没有声明构造器,那么编译器会提供一个隐式inline
默认构造器,也可以自定义默认构造器
Box() { /*perform any required default initialization steps*/}
# 或者设置默认值
// All params have default values
Box (int w = 1, int l = 1, int h = 1): m_width(w), m_height(h), m_length(l){}
只要类声明了构造器,那么编译器不会再提供了默认构造器了
可以删除默认构造器,
- 如果没有其他构造器,那么定义类对象时会报错
- 如果一个类没有默认的构造函数,则不能使用方括号语法单独构造该类的对象数组
Box() = delete;
# 调用报错
Box box; # error: use of deleted function ‘Box::Box()’
# 无法使用方括号语法定义类数组
Box box[3]; # error: use of deleted function ‘Box::Box()’
复制构造器¶
。。。
移动构造器¶
。。。
显式默认和删除的构造函数¶
。。。
构造器执行顺序¶
- 按顺序调用基类和成员构造函数
- 如果类派生自虚拟基类,初始化对象的虚拟基指针
- 如果类具有或继承虚拟函数,则初始化对象的虚拟函数指针。虚拟函数指针指向类的虚拟函数表,以启用对代码的虚拟函数调用的正确绑定
- 执行函数体代码
测试代码如下:
#include <iostream>
using namespace std;
class Contained1 {
public:
Contained1() { cout << "Contained1 ctor\n"; }
};
class Contained2 {
public:
Contained2() { cout << "Contained2 ctor\n"; }
};
class Contained3 {
public:
Contained3() { cout << "Contained3 ctor\n"; }
};
class BaseContainer {
public:
BaseContainer() { cout << "BaseContainer ctor\n"; }
private:
Contained1 c1;
Contained2 c2;
};
class DerivedContainer : public BaseContainer {
public:
DerivedContainer() : BaseContainer() { cout << "DerivedContainer ctor\n"; }
private:
Contained3 c3;
};
int main() {
DerivedContainer dc;
}
- 调用类
DerivedContainer
的基类BaseContainer
的构造器 - 调用类
BaseContainer
的成员构造器Contained1
和Contained2
- 执行类
Contained1
和类Contained2
的构造器函数体 - 执行类
BaseContainer
的构造器函数体 - 调用类
DerivedContainer
的成员构造器Container3
- 执行类
Contained3
的构造器函数体 - 执行类
DerivedContainer
的构造器函数体
Contained1 ctor
Contained2 ctor
BaseContainer ctor
Contained3 ctor
DerivedContainer ctor
继承构造器¶
这是c++11
的新特性,使用using
关键字即可从基类继承构造器
class Base
{
public:
Base() { cout << "Base()" << endl; }
Base(const Base& other) { cout << "Base(Base&)" << endl; }
explicit Base(int i) : num(i) { cout << "Base(int)" << endl; }
explicit Base(char c) : letter(c) { cout << "Base(char)" << endl; }
private:
int num;
char letter;
};
class Derived : Base
{
public:
// Inherit all constructors from Base
using Base::Base;
private:
// Can't initialize newMember from Base constructors.
int newMember{ 0 };
};