文章目录
- 1. 派生类没自己的构造函数,通过 using 关键字使用基类的构造函数
- 2. 派生类有自己的构造函数,派生类的构造函数优先被调用
- 3. 小结
1. 派生类没自己的构造函数,通过 using 关键字使用基类的构造函数
默认情况下,派生类会继承基类的所有成员,包括数据成员和函数成员,但不会继承基类的构造函数和析构函数,因为构造函数和析构函数的作用是创建和销毁对象,派生类通常需要有自己的构造和析构的逻辑。
但是,C++11 引入了using语句,使得派生类可以通过 using 关键字使用基类的构造函数,更方便地复用基类的构造逻辑。
#include <iostream>
#include <string>
using namespace std;
class Base
{
protected:int x;
public:// 基类的构造函数Base(int val=0 ) :x(val){cout << "Base constructor, x: " << x << endl;}// 基类的析构函数~Base(){cout << "Base destructor" << endl;}
};class Derived : public Base
{
public:// 用 using 继承基类的构造函数using Base::Base;// 在派生类中增加其他成员函数void showX(){cout << "Derived showX(), x: " << x << endl;}// 派生类的析构函数~Derived(){cout << "Derived destructor" << endl;}
};int main()
{Derived d1(49); // 有参,派生类没有自己的构造函数,直接调用基类的构造函数d1.showX();Derived d2; // 无参,派生类没有自己的构造函数,直接调用基类的构造函数d2.showX();return 0;
}
运行结果显示
Base constructor, x: 49
Derived showX(), x: 49
Derived destructor
Base destructor
2. 派生类有自己的构造函数,派生类的构造函数优先被调用
例如,在派生类中, using Base::Base;
语句之后增加了如下代码,其余保持不变,
在这种情况下,由于派生类已经定义了所有的构造函数,using Base::Base;其实没有任何作用,可以去掉而不影响代码的行为。
Derived(){cout << "Derived no params is called. x: " << x << endl;}Derived(int val):Base(val){cout << "Derived is called. x: " << x << endl;}
int main()
{Derived d1(49); d1.showX();Derived d2; d2.showX();return 0;
}
运行结果显示如下:
Base constructor, x: 49
Derived is called. x: 49
Derived showX(), x: 49
Base constructor, x: 0
Derived no params is called. x: 0
Derived showX(), x: 0
Derived destructor
Base destructor
Derived destructor
Base destructor
当前代码的构造函数调用过程:
Derived d1(49)
;
调用的是派生类的有参构造函数Derived(int val) : Base(val)。在Base(val)的初始化列表中显式调用基类的构造函数Base(int),完成基类部分的初始化。
Derived d2
;
在main中调用时,调用的是派生类的无参构造函数Derived()。在Derived()的构造函数体执行之前,自动调用基类的默认构造函数Base(int val=0)来初始化基类部分。
完整代码如下
#include <iostream>
#include <string>
using namespace std;
class Base
{
protected:int x;
public:// 基类的构造函数Base(int val=0 ) :x(val){ cout << "Base constructor, x: " << x << endl; }// 基类的析构函数~Base() { cout << "Base destructor" << endl; }
};class Derived : public Base
{
public:// 用 using 继承基类的构造函数using Base::Base; // 此时这句话已多余Derived() { cout << "Derived no params is called. x: " << x << endl; }Derived(int val):Base(val) { cout << "Derived is called. x: " << x << endl; }// 在派生类中增加其他成员函数void showX() { cout << "Derived showX(), x: " << x << endl; }// 派生类的析构函数~Derived() { cout << "Derived destructor" << endl; }
};int main(){Derived d1(49); // 派生类构造函数d1.showX();Derived d2; // 派生类构造函数d2.showX();return 0;
}
3. 小结
- 当派生类定义了自己的构造函数(无参或有参)时,派生类的构造函数优先被调用。
- 在派生类的构造过程中,无论是否存在
using Base::Base
,在执行过程中,基类的构造函数总会优先于派生类的构造函数执行,以确保基类部分的正确初始化 - 用 using Base::Base; 可以简化代码,当且仅当派生类没有定义自己的构造函数时,这一机制才生效
-原因:using Base::Base;的主要目的是让派生类继承基类的构造函数。当派生类没有定义相应的构造函数(无参或有参)时,编译器会使用基类的对应构造函数进行对象的初始化。简化代码而已。但是,如果派生类已经定义了与基类构造函数参数相同的构造函数,那么派生类的构造函数会优先被调用,using Base::Base;不会再被使用。