一、默认构造函数
1、=default 和 =delete
= default // 只能用于不带参数的构造函数,不能用于带参,或者普通函数
= delete // 禁止系统给我们生成默认的不带参数的构造函数
2、explicit
一般只带一个默认参数的构造函数前面会加explicit,避免一些数字会隐式的转化成我们的类型
二、复制构造函数
1、系统默认的复制构造函数,是从源对象到目标对象逐字节拷贝。
2、复制构造函数被调用的三种情况
// 1、用一个对象去初始化同类的另一个对象时,会引发复制构造函数被调用
Element p2(p1); // Element 是自定义类型,
Element p2 = p1;
// 如果是下面的情况,是赋值而不是初始化,不会调用复制构造函数
Element p1 , p1;
p2 = p1; // 该句为赋值语句,不是初始化语句
// 2、作为函数的形参,参数传值时,调用了复制构造函数
void Func1(Element ele); // 调用函数的申明
Element p1;
Func1(p1); // 对象作为函数参数传值时,会调用复制构造函数
void Func2(Element& ele); // 调用函数的申明,此时传入的参数是引用类型
Func2(p1); // 如果传入的参数是引用类型,则不会有拷贝构造函数的调用
// 3、自定义类型作为函数的返回值
Element Func() // 该函数返回局部变量a时,调用了复制构造函数,返回一个临时的Element变量
{
Element a;
return a;
}
Func() ; // 当调用这个函数时,如果没有接住这个返回值,则复制构造函数形成的临时变量在执行完这句话后,就析构了。
3、无参构造函数不一定存在,但是复制构造函数总会存在
三、虚析构函数
class Base
{
public:
Base() {
cout << "Base构造" << endl;
}
virtual ~Base() { // 注意:如果此处不是virtual,则delete Base指针时,不会调用子类析构函数
cout << "Base析构" << endl;
}
};
class Element : public Base
{
public:
Element() {
cout << "Element构造" << endl;
}
~Element() {
cout << "Element析构" << endl;
}
};
int main()
{
Base* p = new Element;
delete p; // 注意:如果Base类的析构函数不是虚函数,则该处只会执行Base的析构函数
// 所以,基类的析构函数一定要是虚函数
system("pause");
return 0;
}
小结:基类中如果有虚函数,则基类的析构函数一定要是虚函数,因为这样,当基类指针指向派生类时,在delete 基类指针时才会调用派生类的析构函数