C++繼承中的對象構造與析構和賦值重載詳解

一、構造/析構順序及繼承性

class A
{
private:
	int _a;
public:
	A(int a = 0): _a(a)
	{
		cout << "A()" << this << endl;
	}
	~A()
	{
		cout << "~A()"<< this <<endl;
	}
};

class B : public A
{
private:
	int _b;
public:
	B(int b): _b(b), A()
	{
		cout << "B()" << this << endl;
	}
	~B()
	{
		cout << "~B()"<< this <<endl;
	}
};

在這裡插入圖片描述

結論:

1.構造順序:先構造基類,後構造派生類

2.析構順序:先析構派生類,後析構基類

二、拷貝構造的繼承性

class A
{
private:
	int _a;
public:
	A(int a = 0): _a(a)
	{
		cout << "A()" << this << endl;
	}
	A(const A& src): _a(src._a)
	{
		cout << "A(const A& src)"<< this << endl;
	}
	~A()
	{
		cout << "~A()"<< this <<endl;
	}
};

class B : public A
{
private:
	int _b;
public:
	B(int b): _b(b), A()
	{
		cout << "B()" << this << endl;
	}
	B(const B& src): _b(src._b)
	{
		cout << "B(const B& src)" << this << endl;
	}
	~B()
	{
		cout << "~B()"<< this <<endl;
	}
};

在這裡插入圖片描述

結論:

1.先調用基類缺省的構造函數,後調用派生類的拷貝構造函數

2.若派生類沒有缺省構造函數A(),就會報錯

疑惑:如何去調用基類的拷貝構造而不是缺省構造

#include<iostream>
using namespace std;

class A
{
private:
	int _a;
public:
	A(int a = 0) : _a(a)
	{
		cout << "A()" << this << endl;
	}
	A(const A& src) : _a(src._a)
	{
		cout << "A(const A& src)" << this << endl;
	}
	~A()
	{
		cout << "~A()" << this << endl;
	}
};

class B : public A
{
private:
	int _b;
public:
	B(int b) : _b(b), A()
	{
		cout << "B()" << this << endl;
	}
	B(const B& src) : _b(src._b), A(src)	//發生賦值兼容規則(切片)
	{
		cout << "B(const B& src)" << this << endl;
	}
	~B()
	{
		cout << "~B()" << this << endl;
	}
};
int main()
{
	B b(10);
	B b1(b);
	return 0;
}

在這裡插入圖片描述

結果:

將B類型src傳遞給A類型的A(const A& src)拷貝構造函數,發生瞭賦值兼容規則(切片現象)

三、賦值重載不具有繼承性

#include<iostream>
using namespace std;

class A
{
private:
	int _a;
public:
	A(int a = 0) : _a(a)
	{
		cout << "A()" << this << endl;
	}
	A(const A& src) : _a(src._a)
	{
		cout << "A(const A& src)" << this << endl;
	}
	A& operator=(const A& src)
	{
		if(this != &src)
		{
			_a = src._a;
			cout << "A& operator=(const A& src)" << endl;
		}
	}
	~A()
	{
		cout << "~A()" << this << endl;
	}
};

class B : public A
{
private:
	int _b;
public:
	B(int b) : _b(b), A()
	{
		cout << "B()" << this << endl;
	}
	B(const B& src) : _b(src._b), A(src)	//發生賦值兼容規則(切片)
	{
		cout << "B(const B& src)" << this << endl;
	}
	B& operator=(const B& src)
	{
		if(this != &src)
		{
			_b = src._b;
			cout << "B& operator=(const B& src)" <<  endl;
		}
	}
	~B()
	{
		cout << "~B()" << this << endl;
	}
};
int main()
{
	B b1(10);
	B b2(20);
	b1 = b2;
	return 0;
}

在這裡插入圖片描述

結論:默認情況下僅僅調用瞭派生類的對象的賦值重載,並未調用基類的賦值重載。

解決方案:

#include<iostream>
using namespace std;

class A
{
private:
	int _a;
public:
	A(int a = 0) : _a(a)
	{
		cout << "A()" << this << endl;
	}
	A(const A& src) : _a(src._a)
	{
		cout << "A(const A& src)" << this << endl;
	}
	A& operator=(const A& src)
	{
		if(this != &src)
		{
			_a = src._a;
			cout << "A& operator=(const A& src)" << endl;
		}
	}
	~A()
	{
		cout << "~A()" << this << endl;
	}
};

class B : public A
{
private:
	int _b;
public:
	B(int b) : _b(b), A()
	{
		cout << "B()" << this << endl;
	}
	B(const B& src) : _b(src._b), A(src)	//發生賦值兼容規則(切片)
	{
		cout << "B(const B& src)" << this << endl;
	}
	B& operator=(const B& src)
	{
		if(this != &src)
		{
			*(A*)this = src;	//將調用基類賦值重載
			_b = src._b;
			cout << "B& operator=(const B& src)" <<  endl;
		}
	}
	~B()
	{
		cout << "~B()" << this << endl;
	}
};
int main()
{
	B b1(10);
	B b2(20);
	b1 = b2;
	return 0;
}

在這裡插入圖片描述

總結

本篇文章就到這裡瞭,希望能夠給你帶來幫助,也希望您能夠多多關註WalkonNet的更多內容!     

推薦閱讀: