[c++學習筆記10]:類和對象——繼承

有些類與類之間存在特殊的關係。
我們發現,定義這些類時,下級別的成員除了擁有上一級的共性,還有自己的特性。
這個時候我們就可以考慮利用繼承的技術,減少重複代碼。

繼承的好處:
++可減少重複代碼++

一、基本語法

class A : public B;
A 類稱爲子類 或 派生類
B 類稱爲父類 或 基類

例如我們看到很多網站中,都有公共的頭部,公共的底部,甚至公共的左側列表,只有中心內容不同。

接下來我們分別利用普通寫法和繼承的寫法來實現網頁中的內容,看一下繼承存在的意義以及好處。
普通實現:(繁瑣,難以實現,內容複雜,低級程序員)

//Java頁面
class Java 
{
public:
	void header()
	{
		cout << "首頁、公開課、登錄、註冊...(公共頭部)" << endl;
	}
	void footer()
	{
		cout << "幫助中心、交流合作、站內地圖...(公共底部)" << endl;
	}
	void left()
	{
		cout << "Java,Python,C++...(公共分類列表)" << endl;
	}
	void content()
	{
		cout << "JAVA學科視頻" << endl;
	}
};
//Python頁面
class Python
{
public:
	void header()
	{
		cout << "首頁、公開課、登錄、註冊...(公共頭部)" << endl;
	}
	void footer()
	{
		cout << "幫助中心、交流合作、站內地圖...(公共底部)" << endl;
	}
	void left()
	{
		cout << "Java,Python,C++...(公共分類列表)" << endl;
	}
	void content()
	{
		cout << "Python學科視頻" << endl;
	}
};
//C++頁面
class CPP 
{
public:
	void header()
	{
		cout << "首頁、公開課、登錄、註冊...(公共頭部)" << endl;
	}
	void footer()
	{
		cout << "幫助中心、交流合作、站內地圖...(公共底部)" << endl;
	}
	void left()
	{
		cout << "Java,Python,C++...(公共分類列表)" << endl;
	}
	void content()
	{
		cout << "C++學科視頻" << endl;
	}
};

void test01()
{
	//Java頁面
	cout << "Java下載視頻頁面如下: " << endl;
	Java ja;
	ja.header();
	ja.footer();
	ja.left();
	ja.content();
	cout << "--------------------" << endl;

	//Python頁面
	cout << "Python下載視頻頁面如下: " << endl;
	Python py;
	py.header();
	py.footer();
	py.left();
	py.content();
	cout << "--------------------" << endl;

	//C++頁面
	cout << "C++下載視頻頁面如下: " << endl;
	CPP cp;
	cp.header();
	cp.footer();
	cp.left();
	cp.content();

}

int main() {

	test01();

	system("pause");

	return 0;
}

但是運用繼承的話:
通過繼承,減少很多代碼量,就很舒服。

#include<iostream>
using namespace std;
#include<string>
//函數調用()運算符重載
class Basetool
{
public:
	void head()
	{
		cout << "頁面設置,詳情信息……(頭部信息)" << endl;
	}
	void foot()
	{
		cout << "合作方式,快速加入……(底部信息)" << endl;
	}
	void left()
	{
		cout << "c++,python,java……(左側信息)" << endl;
	}
};
class python: public Basetool
{
public:
	void content()
	{
		cout << "python的界面(內容信息)……" << endl;
	}
};
class cpp : public Basetool
{
public:
	void content()
	{
		cout << "c++的界面(內容信息)……" << endl;
	}
};
class java : public Basetool
{
public:
	void content()
	{
		cout << "java的界面(內容信息)……" << endl;
	}
};
void test01() 
{
	python py;
	py.head();
	py.foot();
	py.left();
	py.content();
	cout << "+++++++++++++++++++++++" << endl;
	cpp cp;
	cp.head();
	cp.foot();
	cp.left();
	cp.content();
	cout << "+++++++++++++++++++++++" << endl;
	java y;
	y.head();
	y.foot();
	y.left();
	y.content();
	cout << "+++++++++++++++++++++++" << endl;

}


int main() {

	test01();

	system("pause");

	return 0;
}

總結:

派生類中的成員,包含兩大部分

一類是從基類繼承過來的,一類是自己增加的成員

從基類繼承過過來的表現其共性,而新增的成員體現了其個性

二、繼承的方式

繼承方式一共有三種:

  • 公共繼承
  • 保護繼承
  • 私有繼承

邏輯如圖:在這裏插入圖片描述

#include<iostream>
using namespace std;
#include<string>
//函數調用()運算符重載
class Base
{
public:
	int m_A;
protected:
	int m_B;
private:
	int m_C;
};
//公共繼承
class Son1 : public Base
{
public:
	void func()
	{
		m_A=32 ; //可訪問 public權限
		m_B=3 ; //可訪問 protected權限,類外不可訪問,在繼承中,兒子可以訪問父親
		//m_C; //不可訪問
	}
};

void test01() 
{
	Son1 s1;
	s1.m_A = 78;//其他類只能訪問到公共權限
	//s1.m_B=2    保護權限類外不可訪問,


}
class Son2 : protected Base
{
public:
	void func()
	{
		m_A; //可訪問 private權限,父類中public成員到子類變爲protected成員
		m_B; //可訪問 private權限,父類中protected成員到子類變爲protected成員
		//m_C; //不可訪問
	}
};
void test02() 
{
	Son2 s;
	//s.m_A; //不可訪問
}
class Son3 :private Base
{
public:
	void func()
	{
		m_A; //可訪問 private權限,父類中public成員到子類變爲private成員
		m_B; //可訪問 private權限,父類中protected成員到子類變爲private成員
		//m_C; //不可訪問
	}
};
void test03()
{
	Son3 f;
	//Son3是私有繼承,所以繼承Son3的屬性在GrandSon3中都無法訪問到
	//m_A;
	//m_B;
	//m_C;
}
class grandson : public Son3
{
public:
	void func()
	{
		m_A = 1;//到了Son3中,m_A,m_B變成了私有,即時是兒子,也訪問不到。
		m_B = 2;
	}
};

int main() {

	test01();
	system("pause");
	return 0;
}

三、繼承中的對象模型

使用開發人員命令工具
進行操作。首先切換到本目錄
然後:
cl /d1 reportSingleClassLayoutSon hello.cpp
報告單個類的佈局+類名。
(tap鍵可補齊)
我們發現:
繼承後,父類的所有都來了包括私有,也佔用空間。

>父類中所有非靜態成員都被繼承下去了
>父類中私有成員被編譯器隱藏了,因此訪問不到,但是確實被繼承下去了。
#include<iostream>
using namespace std;
#include<string>
//函數調用()運算符重載
class Base
{
public:
	int m_A;
protected:
	int m_B;
private:
	int m_C;
};
//公共繼承
class Son : public Base
{
public:
	int m_D;
};
void test01()
{
	//16
	//父類中所有非靜態成員都被繼承下去了
	//父類中私有成員被編譯器隱藏了,因此訪問不到,但是確實被繼承下去了。
	cout << "子類的大小" << sizeof(Son) << endl;
}
int main() {

	test01();
	//test02();

	system("pause");

	return 0;
}


查看對象模型如圖:
在這裏插入圖片描述

四、繼承中構造和析構順序

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章