在继承关系里,如果子类里没有显示定义这六个成员函数,编译器会默认合成的函数
实现一个继承关系里的默认成员函数
class person
{
public:
person(const char* name)
:_name(name)
{
cout << "person()" << endl;
}
person(const person& p)
:_name(p._name)
{
cout << "person(const person())" << endl;
}
person& operator=(const person& p)
{
cout << "person operator=()" << endl;
if (this != &p)
{
_name = p._name;
}
return *this;
}
~person()
{
cout << "~person" << endl;
}
protected:
string _name;
};
class student :public person
{
public:
//子类的构造函数是合成的,将父类的和自己的合成一个
student(const char* name, int num)//子类的构造函数如果没有传参,就要将父类的构造定义为缺省的
:person(name)//子类的构造函数只能初始化自己的成员,父类的部分要调用父类自己的
,_num(num)
{
cout << "student()" << endl;
}
//子类的拷贝构造函数是合成的,要调用父类的拷贝构造
student(const student& s)
:person(s)
, _num(s._num)
{
cout << "student(const student &s)" << endl;
}
student& operator=(const student& s)
{
cout << "student& operator=()" << endl;
if (this != &s)
{
person::operator=(s);//一定要指定作用域,否则会一直递归,导致栈溢出
_num = s._num;
}
return *this;
}
////不能这样定义,这样会构成隐藏,因为所有的析构函数在编译过程中,函数名都会被改写成样的
//~student()
//{
// ~person();
//}
//子类的析构函数不需要调用父类的,自己会清理,子类析构,出了作用域,父类调用自己的析构函数
~student()
{
cout << "~studnet" << endl;
}
private:
int _num;
};
1.构造函数:
- 子类的构造函数是合成的,将父类的和自己的合成一个
- 子类的构造函数只能初始化自己的成员,父类的部分要调用父类自己的
- 子类的构造函数如果没有传参,就要将父类的构造定义为缺省的
2.拷贝构造函数:
- 子类的拷贝构造函数是合成的,要调用父类的拷贝构造
3.赋值运算符重载:
- 子类的赋值运算符重载函数是合成的,要调用父类赋值运算符重载
- 调用父类赋值运算符,一定要指定作用域,否则会一直递归,导致栈溢出
4.析构函数:
- 析构函数不需要用调用父类的,自己会清理;
- 子类析构,出了作用域之后,父类调用自己的析构;先构造父类,后构造子类,先析构子类,后析构父类
- 所有析构函数的函数名在编译过程中,都会被改写为一样的,所以父类子类会构成隐藏
- 要是想在子类的析构函数中调用父类的析构函数,一定要指明作用域
~student()
{
person::~person();
}