继承关系里的六个默认成员函数

在继承关系里,如果子类里没有显示定义这六个成员函数,编译器会默认合成的函数

实现一个继承关系里的默认成员函数

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();

}

猜你喜欢

转载自blog.csdn.net/audience_fzn/article/details/81461533