繼承關係裡的六個預設成員函式

audience_fzn發表於2018-08-06

在繼承關係裡,如果子類裡沒有顯示定義這六個成員函式,編譯器會預設合成的函式

實現一個繼承關係裡的預設成員函式

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

}

 

 

相關文章