首页 > 编程笔记
C++派生类的构造函数和析构函数(入门必读)
在 C++ 中,继承使得派生类的内部包含了基类的成员,因此派生类也必须负责基类成员的构造和析构。
在派生类的构造函数中,至少要完成以下两件事情:
定义派生类的构造函数时,应当在初始化列表中依次写上基类的构造函数和成员的初始化参数。特别是在基类和数据成员的构造函数带有参数的情况下,其参数只能由开发者指定,所以必须显式地初始化。其语法如下:
在派生类构造函数的初始化列表中,编译器先调用基类的构造函数,然后是各个成员的初始化,各个成员的初始化是按照它们定义的顺序进行的。
举个简单的例子:
运行这段代码,输出结果为:
与构造函数不同的是,由于析构函数没有参数,所以基类和新增数据成员的析构可以由编译器代劳,即在编译时由编译器插入相关的析构代码。
派生类的析构与构造顺序刚好相反,其顺序是先调用派生类的析构函数,然后析构派生类新增的成员,最后析构基类对象。
修改上面的程序,为各个类手动添加析构函数:
派生类的构造函数
首先,构造函数是不能被继承的,派生类必须重新定义自己的构造函数。在派生类的构造函数中,至少要完成以下两件事情:
- 构造基类子对象,此过程必须以初始化列表的方式完成;
- 派生类新添加成员的初始化,可以用初始化列表的方式,也可以写在构造函数的内部,本文中采用初始化列表的方式。
定义派生类的构造函数时,应当在初始化列表中依次写上基类的构造函数和成员的初始化参数。特别是在基类和数据成员的构造函数带有参数的情况下,其参数只能由开发者指定,所以必须显式地初始化。其语法如下:
派生类构造函数名(参数列表):基类构造函数名(参数列表), 派生类成员初始化 { ...... //派生类成员初始化的过程也可以写在函数内部 }例如,基类的构造函数是:
Base(int b);派生类新增的成员变量是:
int m_a;那么派生类的构造函数应该定义为:
Derived(int b, int a):Base(b), m_a(a){ //...... 也可以将 m_a=a; 写在函数内部 }对于有默认构造函数的基类,定义派生类的构造函数时可以不显式地调用基类的构造函数。如果派生类新增成员变量的类型是内置的数据类型,或者是具有默认构造函数的类,那么编译器也会自动添加成员变量的初始化代码。
在派生类构造函数的初始化列表中,编译器先调用基类的构造函数,然后是各个成员的初始化,各个成员的初始化是按照它们定义的顺序进行的。
举个简单的例子:
#include <iostream> class Base { public: Base() { std::cout << "Base constructor" << std::endl; } }; class MemberA { public: MemberA() { std::cout << "MemberA constructor" << std::endl; } }; class MemberB { public: MemberB() { std::cout << "MemberB constructor" << std::endl; } }; class Derived : public Base { private: MemberA memberA; MemberB memberB; public: // 派生类构造函数 Derived() : memberB(), memberA() { std::cout << "Derived constructor" << std::endl; } }; int main() { Derived d; return 0; }示例中有一个基类 Base 和两个成员类 MemberA 和 MemberB,然后有一个派生类 Derived,其中包含了这两个成员。在 Derived 的构造函数里,可以看到初始化列表中首先是 memberA,然后是 memberB。
运行这段代码,输出结果为:
Base constructor
MemberA constructor
MemberB constructor
Derived constructor
派生类的析构函数
和构造函数一样,析构函数也不能被继承,所以派生类也需要有自己的析构函数。与构造函数不同的是,由于析构函数没有参数,所以基类和新增数据成员的析构可以由编译器代劳,即在编译时由编译器插入相关的析构代码。
派生类的析构与构造顺序刚好相反,其顺序是先调用派生类的析构函数,然后析构派生类新增的成员,最后析构基类对象。
修改上面的程序,为各个类手动添加析构函数:
#include <iostream> class Base { public: Base() { std::cout << "Base constructor" << std::endl; } ~Base() { std::cout << "Base destructor" << std::endl; } }; class MemberA { public: MemberA() { std::cout << "MemberA constructor" << std::endl; } ~MemberA() { std::cout << "MemberA destructor" << std::endl; } }; class MemberB { public: MemberB() { std::cout << "MemberB constructor" << std::endl; } ~MemberB() { std::cout << "MemberB destructor" << std::endl; } }; class Derived : public Base { private: MemberA memberA; MemberB memberB; public: Derived() : memberB(), memberA() { std::cout << "Derived constructor" << std::endl; } ~Derived() { std::cout << "Derived destructor" << std::endl; } }; int main() { Derived d; return 0; }运行结果为:
Base constructor
MemberA constructor
MemberB constructor
Derived constructor
Derived destructor
MemberB destructor
MemberA destructor
Base destructor