1. 程式人生 > 其它 >C++_繼承(上)

C++_繼承(上)

技術標籤:C++c++

C++(面向物件)

類和物件

繼承

繼承是面向物件三大特性之一

有些類與類之間存在特殊關係,下級別成員除了擁有上一級的共性,還有自己的特性,這時需要利用繼承的技術,減少重複程式碼。

例:很多網站中,有公共頭部,公共底部,甚至公共的左側列表,只有中心內容不同,接下來分別利用普通寫法和繼承寫法實現網頁內容(黑馬程式設計師網站首頁)。

普通寫法

#include <iostream>
using namespace std;

//普通寫法
class Java{
	public:
		void Header()
		{
			cout<<"黑馬程式設計師"<<endl; 
		}
		
		void Footer()
		{
			cout<<"相關網站和站內地圖"<<endl; 
		}
		
		void Lefter()
		{
			cout<<"Java,C++,Python等"<<endl;
		}
		
		void Content()
		{
			cout<<"這是Java語言的相關內容"<<endl;
		}
};

class Cpp{
	public:
		void Header()
		{
			cout<<"黑馬程式設計師"<<endl; 
		}
		
		void Footer()
		{
			cout<<"相關網站和站內地圖"<<endl; 
		}
		
		void Lefter()
		{
			cout<<"Java,C++,Python等"<<endl;
		}
		
		void Content()
		{
			cout<<"這是C++語言的相關內容"<<endl;
		}
};

class Python{
	public:
		void Header()
		{
			cout<<"黑馬程式設計師"<<endl; 
		}
		
		void Footer()
		{
			cout<<"相關網站和站內地圖"<<endl; 
		}
		
		void Lefter()
		{
			cout<<"Java,C++,Python等"<<endl;
		}
		
		void Content()
		{
			cout<<"這是Python語言的相關內容"<<endl;
		}
};

void test01()
{
	cout<<"Java的介面為:"<<endl; 
	Java ja;
	ja.Header();
	ja.Lefter();
	ja.Content();
	ja.Footer();
	cout<<"-----------------------"<<endl;
	cout<<"Cpp的介面為:"<<endl; 
	Cpp cp;
	cp.Header();
	cp.Lefter();
	cp.Content();
	cp.Footer();
	cout<<"-----------------------"<<endl;
	cout<<"Python的介面為:"<<endl; 
	Python py;
	py.Header();
	py.Lefter();
	py.Content();
	py.Footer();
}

int main()
{
	test01();
	
	return 0;
 } 

繼承寫法

#include <iostream>
using namespace std;

//繼承寫法
class Base{  //父類 
	public:
		void Header()
		{
			cout<<"黑馬程式設計師"<<endl; 
		}
		
		void Footer()
		{
			cout<<"相關網站和站內地圖"<<endl; 
		}
		
		void Lefter()
		{
			cout<<"Java,C++,Python等"<<endl;
		}
};

//子類 
class Java : public Base{
	public:	
		void Content()
		{
			cout<<"這是Java語言的相關內容"<<endl;
		}
};

class Cpp : public Base{
	public:
		void Content()
		{
			cout<<"這是C++語言的相關內容"<<endl;
		}
};

class Python : public Base{
	public:
		void Content()
		{
			cout<<"這是Python語言的相關內容"<<endl;
		}
};

void test01()
{
	cout<<"Java的介面為:"<<endl; 
	Java ja;
	ja.Header();
	ja.Lefter();
	ja.Content();
	ja.Footer();
	cout<<"-----------------------"<<endl;
	cout<<"Cpp的介面為:"<<endl; 
	Cpp cp;
	cp.Header();
	cp.Lefter();
	cp.Content();
	cp.Footer();
	cout<<"-----------------------"<<endl;
	cout<<"Python的介面為:"<<endl; 
	Python py;
	py.Header();
	py.Lefter();
	py.Content();
	py.Footer();
}

int main()
{
	test01();
	
	return 0;
 } 

同樣的結果

繼承的好處:減少重複程式碼

1.繼承的基本語法

  • class 子類 :繼承方式 父類
  • 子類也稱派生類,父類也稱基類
  • 派生類中的成員,包含兩大部分:一類是從基類繼承過來的,一類是自己增加的成員;從基類繼承過來的表現其共性,而新增的成員體現其個性。

2.繼承方式

  • 繼承方式一共有三種:公共繼承(public);保護繼承(protected);私有繼承(private)
  • class B :繼承方式 A (B為子類,A為父類)
#include <iostream>
using namespace std;

 //父類 
class Base{ 
	public:
		int m_A;
	protected:
		int m_B;
	private:
		int m_C;	 
};

//子類 
class Son1 : public Base{ //繼承方式為公共型別 
	public:	
		void func()
		{
			m_A = 10; //公共型別 
			m_B = 10; //保護型別 
			//m_C = 10; //私有型別,子類無法訪問 
		}
};

class Son2 : protected Base{ //繼承方式為保護型別 
	public:	
		void func()
		{
			m_A = 100; //保護型別 
			m_B = 100; //保護型別 
			//m_C = 100; //父類的私有型別,子類無法訪問
		}
};

class Son3 : private Base{
	public:	
		void func()
		{
			m_A = 1000; //私有型別 
			m_B = 1000; //私有型別 
			//m_C = 1000; //父類的私有型別,子類無法訪問 
		}
};

void test01()
{
	Son1 s1;
	s1.m_A = 100;  //類內的公共型別,類外可以訪問
	//s1.m_B = 100;  //類內的保護型別,類外不可以訪問
}

void test02()
{
	Son2 s2;
	//s2.m_A = 1000;  //類內的保護型別,類外不可以訪問
	//s2.m_B = 1000;  //類內的保護型別,類外不可以訪問
}

void test03()
{
	Son3 s3;
	//s3.m_A = 10000;  //類內的私有型別,類外不可以訪問
	//s3.m_B = 10000;  //類內的私有型別,類外不可以訪問
}

int main()
{
	test01();
	test02();
	test03();
	
	return 0;
 } 

3.繼承中的物件模型

  • 問題:從父類繼承過來的成員,哪些屬於子類物件中?
#include <iostream>
using namespace std;

class Base{ 
	public:
		int m_A;
	protected:
		int m_B;
	private:
		int m_C;	 
};

class Son : public Base{ 
	public:	
		int m_D;
};

void test01()
{
	Son s;
	cout<<sizeof(s)<<endl;  //16
}

int main()
{
	test01();
	
	return 0;
 } 

總結:父類中非靜態成員屬性都會被子類繼承下去,父類中的私有成員屬性被編譯器隱藏,因此子類訪問不到,但確實被繼承下去。

:在Visual Studio中利用開發人員命令提示符可以檢視物件模型,報告單個類佈局。在檔案的目錄下:命令(cl /d1 reportSingleClassLayout類名 “檔名”),例如:


4.繼承中構造和析構的順序

  • 子類繼承父類後,當建立子類物件,也會呼叫父類的建構函式
  • 問題:父類子類的建構函式和解構函式順序誰先誰後?
#include <iostream>
using namespace std;

class Base{ 
	public:
		Base()
		{
			cout<<"父類的建構函式"<<endl; 
		}
		~Base()
		{
			cout<<"父類的解構函式"<<endl;
		}
};

class Son : public Base{ 
	public:	
		Son()
		{
			cout<<"子類的建構函式"<<endl; 
		}
		~Son()
		{
			cout<<"子類的解構函式"<<endl;
		}
};

void test01()
{
	Son s;  //先構造父類,再構造子類,析構與構造相反 
}

int main()
{
	test01();
	
	return 0;
 } 

總結:繼承中,先呼叫父類的建構函式,再呼叫子類的建構函式,解構函式與建構函式相反。