前边的学习,我们知道了C++中的构造函数、析构函数、类之间的继承,那么当子类继承父类后,我们如何去初始化继承自父类的成员变量?
C++中子类中可以定义构造函数
- 在子类的构造函数中直接通过初始化列表或者赋值的方式进行初始化
-调用父类构造函数进行初始化
但是对于在子类中通过初始化列表或赋值的方式对父类进行初始化,当父类成员为private属性时,便无法直接访问,所以我们一般采用第二种方式,及使用父类构造函数对父类成员进程初始化。
在子类中调用父类构造函数,分为隐式调用与显示调用
- 隐式调用:适用于无参构造函数与参数为默认值得构造函数
- 显示调用:通过初始化列表进行调用,适用于所有构造函数
下边代码展示一下:
#include <iostream>
#include <string>
using namespace std;
class Parent
{
private:
int m_value;
string m_str;
public:
Parent() //父类无参构造函数
{
m_value = 0;
m_str = "hello";
cout << "Parent()" << endl;
}
Parent(int i, string str) //父类带参构造函数
{
m_value = i;
m_str = str;
cout << "Parent(int i, string str)" << endl;
}
int getVlaue()
{
return m_value;
}
string getString()
{
return m_str;
}
};
class Child : public Parent
{
public:
Child() //隐式调用父类无参构造函数parent()
{
cout << "Child()" << endl;
}
Child(int n, string str):Parent(n, str) //通过初始化列表显示调用父类构造函数Parent(int i, string str)
{
cout << "Child(int n, string str)" << endl;
}
};
int main()
{
Child C1; //调用子类无参构造函数,父类初始化调用的也为无参构造函数
cout << "C1.getVlaue() = " << C1.getVlaue() << endl;
cout << "C1.getString() = " << C1.getString() << endl << endl;
Child C2(100, "Fight"); //调用子类有参构造函数,同时在初始化列表调用父类构造函数
cout << "C2.getVlaue() = " << C2.getVlaue() << endl;
cout << "C2.getString() = " << C2.getString() << endl;
system("pause");
}
编译输出
从输出结果看,C1我们是隐式调用父类无参构造函数,成员变量的值也为无参构造函数里初始化的值;C2是通过初始化列表显示的调用父类带参构造,成员变量值变为构造函数参数的值。
对象创建时的构造函数的调用顺序
-先调用父类的构造函数
-后调用成员变量的构造函数
-再调用自身的构造函数
先父母 ->后客人-> 再自己
对象销毁时的析构函数的调用顺序刚好与构造函数调用顺序相反
-先调用自身的构造函数
-后调用成员变量的构造函数
-再调用父类的构造函数
先自己 ->后客人-> 再父母
下边以一个简单的代码验证一下:
#include <iostream>
#include <string>
using namespace std;
class Parent
{
public:
Parent()
{
cout << "Parent()" << endl;
}
Parent(string str)
{
cout << "Parent(string str)" << endl;
}
~Parent()
{
cout << "~Parent()" << endl;
}
};
class Guest
{
public:
Guest()
{
cout << "Guest()" << endl;
}
Guest(string str)
{
cout << "Guest(string str)" << endl;
}
~Guest()
{
cout << "~Guest()" << endl;
}
};
class Child : public Parent
{
private:
Guest m_Guest;
public:
Child() //隐式调用父类及成员的构造函数(无参构造函数)
{
cout << "Child()" << endl;
}
Child(string str):Parent(str), m_Guest(str) //显示调用父类及成员的构造函数(带参构造函数)
{
cout << "Child(string str)" << endl;
}
~Child()
{
cout << "~Child()" << endl;
}
};
int main()
{
{
Child C1;
}
cout << endl;
{
Child C2("hello");
}
system("pause");
}
编译输出:
从输出结果看,构造函数与析构函数的调用顺序却是如我们所说的那样,并且分别隐式与显示调用父类与成员对象的构造函数
总结:
- 子类对象在创建时需要调用父类构造函数进行初始化
- 先执行父类构造函数再执行成员的构造函数
- 父类构造函数显示调用需要在初始化列表中进行
- 子类对象在销毁时需要调用父类析构函数进行清理
- 析构顺序与构造顺序相反