c++继承中的构造与析构方法是什么
这篇文章主要讲解了"c++继承中的构造与析构方法是什么",文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习"c++继承中的构造与析构方法是什么"吧!
我们思考下这个问题:如何初始化父类成员?父类构造函数和子类构造函数有何关系呢?在子类中可以定义构造函数,子类构造函数必须对继承而来的成员进行初始化:a> 直接通过初始化列表或者赋值的方式进行初始化;b> 调用父类构造函数进行初始化。
下来我们来说说父类构造函数在子类中的调用方式,分为两种:a> 默认调用:适用于无参构造函数和使用默认参数的构造函数;b> 显示调用:通过初始化列表进行调用,适用于所有父类构造函数。那么隐式调用是在子类的构造函数中啥都不加,显示调用时在子类构造函数后加上父类构造函数,如下所示
下来我们就对子类的构造函数一探究竟
#include#include using namespace std;class Parent{public: Parent(string s) { cout << "Parent(string s): " << s << endl; }};class Child : public Parent{public: Child() { cout << "Child()" << endl; } Child(string s) : Parent(s) { cout << "Child(string s): " << s << endl; }};int main(){ Child c; Child cc("cc"); return 0;}
我们先来分析下,在子类 Child 中,它定义的第一个构造函数显然是隐式调用父类的构造函数。但是在父类的构造函数中,我们既没有定义无参构造函数,也没有定义默认参数的构造函数,所以这个隐式调用肯定会出错。而第二个对象 cc 是进行显示调用的,所以它不会报错。我们来看看编译结果
它报错说第 19 行出错,也就是子类的隐调用出错了,下来我们在父类中通过一个无参构造函数,来看看编译是否还会出错呢
我们看到编译通过了,并且也完美运行。我们来说说子类对象的构造规则:a> 子类对象在创建时会首先调用父类的构造函数;b> 先执行父类的构造函数再执行子类的构造函数;c> 父类构造函数可以被隐式调用或者显示调用。那么子类对象的创建时构造函数的调用又有什么顺序呢?1、调用父类的构造函数;2、调用成员变量的构造函数;3、调用类自身的构造函数。对此,有唐长老总结的一个口诀心法:先父母,后客人,再自己。
下来我们通过编程来看看子类创建时构造函数的执行顺序
#include#include using namespace std;class Object{ string ms;public: Object(string s) { ms = s; cout << "Object(string s): " << ms << endl; }};class Parent : public Object{ string ms;public: Parent() : Object("Default") { ms = "Default"; cout << "Parent()" << endl; } Parent(string s) : Object(s) { ms = s; cout << "Parent(string s): " << s << endl; }};class Child : public Parent{ Object mOb1; Object mOb2; string ms;public: Child() : mOb1("Default 1"), mOb2("Default 2") { ms = "Default"; cout << "Child()" << endl; } Child(string s) : Parent(s), mOb1(s + " 1"), mOb2(s + " 2") { ms = s; cout << "Child(string s): " << s << endl; }};int main(){ Child c; // c output: // Object(string s): Default // Parent() // Object(string s): Default 1 // Object(string s): Default 2 // Child() cout << endl; Child cc("cc"); // cc output: // Object(string s): Default // Parent(string s) : cc // Object(string s): cc 1 // Object(string s): cc 2 // Child(string s): cc return 0;}
我们来分析下,类Child c 创建时首先会隐式调用它的父类构造函数 Parent() : Object("Default"),而 Parent 创建时会先调用它的父类 Object 的构造函数 Object("Default")。再来调用成员对象 mOb1 和 mOb2 的构造函数 mOb1("Default 1"), mOb2("Default 2"),最后调用自己的构造函数 Child()。所以最后打印的应该和我们程序中写的是一致的。再来看看对象 cc 的创建过程,因为它是显示调用,所以会调用构造函数 Parent(s) ,而 Parent 的父类 Object 也会调用构造函数 Object(string s) 。额庵后调用成员对象 mOb1 和 mOb2 的构造函数 mOb1(s + "1"), mOb2(s + "2"),最后调用自己的构造函数 Child(string s)。打印的应该也和我们在程序中写的一致。我们来看编译结果
结果和我们分析的是一致的。那么再来看看析构函数的调用顺序,它跟构造函数的顺序刚好相反:1、执行自身的析构函数;2、执行成员变量的析构函数;3、执行父类的析构函数。依旧是在上面的程序基础之上,来看看析构函数的执行顺序。
#include#include using namespace std;class Object{ string ms;public: Object(string s) { ms = s; cout << "Object(string s): " << ms << endl; } ~Object() { cout << "~Object() : " << ms << endl; }};class Parent : public Object{ string ms;public: Parent() : Object("Default") { ms = "Default"; cout << "Parent()" << endl; } Parent(string s) : Object(s) { ms = s; cout << "Parent(string s): " << s << endl; } ~Parent() { cout << "~Parent() : " << ms << endl; }};class Child : public Parent{ Object mOb1; Object mOb2; string ms;public: Child() : mOb1("Default 1"), mOb2("Default 2") { ms = "Default"; cout << "Child()" << endl; } Child(string s) : Parent(s), mOb1(s + " 1"), mOb2(s + " 2") { ms = s; cout << "Child(string s): " << s << endl; } ~Child() { cout << "~Child() : " << ms << endl; }};int main(){ Child cc("cc"); return 0;}
我们来看看编译结果
感谢各位的阅读,以上就是"c++继承中的构造与析构方法是什么"的内容了,经过本文的学习后,相信大家对c++继承中的构造与析构方法是什么这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是,小编将为大家推送更多相关知识点的文章,欢迎关注!