欧美一级特黄大片做受成人-亚洲成人一区二区电影-激情熟女一区二区三区-日韩专区欧美专区国产专区

【C++面向?qū)ο蟪绦蛟O(shè)計(jì)】CH5繼承與派生-創(chuàng)新互聯(lián)

目錄

創(chuàng)新互聯(lián)建站一直秉承“誠信做人,踏實(shí)做事”的原則,不欺瞞客戶,是我們最起碼的底線! 以服務(wù)為基礎(chǔ),以質(zhì)量求生存,以技術(shù)求發(fā)展,成交一個(gè)客戶多一個(gè)朋友!為您提供網(wǎng)站建設(shè)、成都做網(wǎng)站、成都網(wǎng)頁設(shè)計(jì)、小程序開發(fā)、成都網(wǎng)站開發(fā)、成都網(wǎng)站制作、成都軟件開發(fā)、成都App制作是成都本地專業(yè)的網(wǎng)站建設(shè)和網(wǎng)站設(shè)計(jì)公司,等你一起來見證!

前言

一、繼承與派生的概念

二、派生類的聲明方式

1.格式

2.【例】假定已經(jīng)聲明一個(gè)基類student,在它基礎(chǔ)上通過單繼承建立一個(gè)派生類student1。

三、派生類的構(gòu)成

四、派生類成員的訪問屬性

前言

1.公有繼承

(1)公有基類在派生類中的訪問屬性

(2)【例5.1】派生類訪問公有繼承的基類成員

(3)【例】公有繼承舉例

2.私有繼承

(1)私有基類在派生類中的訪問屬性

(2)【例5.2】將例5.1中公有繼承改為私有繼承

3.保護(hù)成員和保護(hù)繼承

(1)保護(hù)基類在派生類中的訪問屬性

(2)【例5.3】在派生類中訪問保護(hù)成員

4.多級(jí)派生時(shí)的訪問屬性

(1)介紹

(2)【例5.4】多級(jí)派生類的訪問屬性。如果聲明了以下的了類。

五、類型兼容規(guī)則

1.規(guī)則

2.類型兼容規(guī)則舉例

3.基類與派生類的對(duì)應(yīng)關(guān)系

4.多繼承時(shí)派生類的聲明

5.多繼承舉例

6.繼承與派生的目的

六、派生類的構(gòu)造函數(shù)和析構(gòu)函數(shù)

前言——派生類的構(gòu)造函數(shù)?

1.簡單的派生類的構(gòu)造函數(shù)

(1)介紹

(2)【例5.5】簡單派生類的構(gòu)造函數(shù)

(3)單一繼承時(shí)的構(gòu)造函數(shù)舉例

2.有子對(duì)象的派生類的構(gòu)造函數(shù)

(1)介紹

(2)【例】

3.多層派生時(shí)的構(gòu)造函數(shù)

(1)介紹

(2)舉例

4.派生類構(gòu)造函數(shù)的特殊形式

5.派生類的析構(gòu)函數(shù)

(1)介紹

(2)單一繼承時(shí)構(gòu)造函數(shù)、析構(gòu)函數(shù)舉例

七、多重繼承

1.聲明多重繼承的方法

(1)介紹

(2)【例5.8】

2.多重繼承派生類的構(gòu)造函數(shù)

(1)派生類構(gòu)造函數(shù)舉例

(2)同名隱藏規(guī)則

(3)多繼承同名隱藏舉例

3.多重繼承引起的二義性問題

(1)介紹

(2)二義性問題舉例(一)

(3)二義性的解決方法

(4)二義性問題舉例(二)?

(5)多重繼承的同名問題


前言

? 面向?qū)ο蟪绦蛟O(shè)計(jì)有四個(gè)主要特點(diǎn):抽象、封裝、繼承和多態(tài)性。本文主要介紹有關(guān)繼承的知識(shí),在下一篇文章介紹多態(tài)性。

一、繼承與派生的概念

? C++的繼承機(jī)制實(shí)現(xiàn)軟件可重用。有時(shí)兩個(gè)類的內(nèi)容基本相同或有一部分相同。例如已聲明了類student:

class Student
{ 
	private :
	   int num;
	   string name;
	   char sex; 
    public:
	  	void display( )
	    {
			cout<<"num: "<

? 如果另一個(gè)部門除了需要已有的數(shù)據(jù)外,還需要地址信息,你可以再聲明另一個(gè)類:

class Student1
{
	private :
	    int num;
	    string name;
	    char sex;
	    char addr[20]; 
    public:
		void display()
	    { 
			cout<<"num: "<

? 可以看到新類中大部分成員是原來已有的。人們自然會(huì)想到能否利用原來聲明的類student,加上新內(nèi)容即可,以減少重復(fù)的工作。這就引出了C++的繼承機(jī)制。

? 所謂繼承是在已存在的類A的基礎(chǔ)上建立一個(gè)新類B。類A稱為基類或父類,類B稱為派生類或子類。子類從父類獲得其已有的特性,這種現(xiàn)象稱作類的繼承。從另一個(gè)角度看從父類產(chǎn)生子類,稱作類的派生。

? 一個(gè)基類可以派生出多個(gè)派生類,每個(gè)派生類又可以作為基類再派生新的派生類。一個(gè)派生類只從一個(gè)基類派生,稱作單繼承。

? 一個(gè)派生類也可從多個(gè)基類派生,也就是說一個(gè)派生類可以有兩個(gè)或多個(gè)基類。一個(gè)派生類有兩個(gè)或多個(gè)基類的稱為多重繼承?;惡团缮惖年P(guān)系可以表述為:派生類是基類的擴(kuò)充,而基類是派生類的抽象。

二、派生類的聲明方式 1.格式

? 使用派生類要先聲明,聲明的格式為:

class  派生類名: [繼承方式] 基類名
{      
    派生類新增成員聲明    
};

? 繼承方式包括:public、private、protected。如果省略,默認(rèn)為private。

2.【例】假定已經(jīng)聲明一個(gè)基類student,在它基礎(chǔ)上通過單繼承建立一個(gè)派生類student1。
class Student1: public Student
{  
	private:
	    int age;
	    string addr;
    public:
	    void display_1()
	    {  
			cout<<"age: "<
三、派生類的構(gòu)成

? 派生類中的成員包括從基類繼承過來的成員和自己增加的成員。繼承基類成員體現(xiàn)了同一基類的派生類都具有的共性,而新增加的成員體現(xiàn)了派生類的個(gè)性。

  • 從基類接受成員:派生類將基類除構(gòu)造函數(shù)和析構(gòu)函數(shù)外的所有成員接收過來
  • 調(diào)整從基類接受的成員:一方面可以通過繼承方式改變基類成員在派生類中的訪問屬性,另一方面可以在派生類中聲明一個(gè)與基類成員同名的成員屏蔽基類的同名成員,注意如是成員函數(shù)不僅要函數(shù)名相同,而且函數(shù)的參數(shù)也要相同,屏蔽的含義是用新成員取代舊成員
  • 在聲明派生類時(shí)增加成員:它體現(xiàn)了派生類對(duì)基類功能的補(bǔ)充
  • 在聲明派生類時(shí),還要自己定義派生類的構(gòu)造函數(shù)
四、派生類成員的訪問屬性 前言

? 派生類中包含了基類成員和派生類成員,就產(chǎn)生了這兩部分成員的關(guān)系和訪問屬性的問題。這個(gè)關(guān)系由基類成員的訪問屬性和派生類的繼承方式組合決定。

1.公有繼承 (1)公有基類在派生類中的訪問屬性

? 當(dāng)派生類的繼承方式為public(公有)屬性時(shí),在派生類中,基類的公有成員和保護(hù)成員在派生類中的訪問屬性沒有變化,即分別作為派生類的公有成員和保護(hù)成員,派生類的成員可以直接訪問它們。但是,派生類的成員無法直接訪問基類的私有成員。保護(hù)私有成員是一條重要的原則。

(2)【例5.1】派生類訪問公有繼承的基類成員
class Student1: public Student
{
	private:
	    int age;
	    string addr; 
	public:
	   void get_value_1()
			{
				cin>>age>>addr;
			}
	   void display_1()
	    {  
			//cout<<"num: "<

【解釋】

由于基類的私有成員對(duì)派生類說是不能訪問的,所以派生類的成員函數(shù)display_1不能直接訪問基類的私有成員,只能通過基類的公有成員函數(shù)訪問基類的私有成員。

? 因?yàn)槭枪欣^承,基類的公有成員在派生類中仍是公有,所以派生類的對(duì)象可以通過基類的公有成員函數(shù)訪問基類的私有數(shù)據(jù)成員,也可以在派生類的成員函數(shù)中調(diào)用基類的公有成員函數(shù),訪問基類的私有數(shù)據(jù)成員。

方法一:

int main()
{	
	Student1 stud1;
	…  … 
	stud1.display();
	stud1.display_1();
	return 0;
}

方法二:

void display_1()
{ 	
	display();    //派生類成員調(diào)用基類公有成員
	cout<<"age: "<
(3)【例】公有繼承舉例
class Point 
{	//基類Point類的聲明
	public:	//公有函數(shù)成員
		void InitP(float xx = 0, float yy = 0) 
		{
			X = xx;
			Y = yy;
		}
		void Move(float xOff, float yOff) 
		{
			X += xOff;
			Y += yOff;
		}
		float GetX() 
		{
			return X;
		}
		float GetY() 
		{
			return Y;
		}
	private:	//私有數(shù)據(jù)成員
		float X, Y;
};

class Rectangle: public Point 
{ //派生類聲明
	public:	//新增公有函數(shù)成員
		void InitR(float x, float y, float w, float h) 
		{
			InitP(x, y);    //調(diào)用基類公有成員函數(shù)
			W = w;
			H = h;
		}
		float GetH() 
		{
			return H;
		}
		float GetW() 
		{
			return W;
		}
	private:	//新增私有數(shù)據(jù)成員
		float W, H;
};
#include#includeusing namespace std;

int main() 
{
	Rectangle rect;
	rect.InitR(2, 3, 20, 10);
	//通過派生類對(duì)象訪問基類公有成員
	rect.Move(3, 2);
	cout<< rect.GetX()<< ','
	<< rect.GetY()<< ','
	<< rect.GetH()<< ','
	<< rect.GetW()<< endl;
	return 0;
}

2.私有繼承 (1)私有基類在派生類中的訪問屬性

? 在派生類中,基類的公有成員和保護(hù)成員作為派生類的私有成員,派生類的成員可以直接訪問他們,而派生類的成員無法直接訪問基類的私有成員。

? 在派生類的外部,派生類的對(duì)象無法訪問基類的全部對(duì)象。

? 私有繼承之后,全部基類成員在派生類中都成為了私有成員或不可訪問的成員,無法進(jìn)一步派生。私有成員一般很少使用。

(2)【例5.2】將例5.1中公有繼承改為私有繼承
class Student 
{
	private :
		int num;
		string name;
		char sex;
	public:
		void display( ) 
		{
			cout<< "num: "<< num<< endl;
			cout<< "name: "<< name<< endl;
			cout<< "sex: "<< sex<< endl;
		}
};

class Student1: private Student 
{
	private:
		int age;
		string addr;
	public:
		void display_1() 
		{
			display();
			cout<< "age: "<< age<< endl;       //  正確
			cout<< "address: "<< addr<< endl;	//  正確
		}
};

int main() 
{
	Student1 stud1;
	stud1.display_1();
	return 0;
}

3.保護(hù)成員和保護(hù)繼承 (1)保護(hù)基類在派生類中的訪問屬性

? 當(dāng)派生類的繼承方式為protected繼承屬性時(shí),在派生類中,基類的公有成員和保護(hù)成員均作為派生類的保護(hù)成員,派生類的成員可以直接訪問他們,而派生類的成員無法訪問基類的私有成員。

? 在派生類的外部,派生類的對(duì)象無法訪問基類的全部成員。

? 如果基類只進(jìn)行了一次派生,則保護(hù)繼承和私有繼承的功能完全相同,但保護(hù)繼承可以進(jìn)一步派生,而私有繼承則不可以,兩者具有實(shí)質(zhì)性差別。

(2)【例5.3】在派生類中訪問保護(hù)成員
class Student 
{              //    聲明基類
	protected :                   //    基類保護(hù)成員
		int num;
		string name;
		char sex;
	public:                          //    基類公用成員
		void display( );
};

class Student1: protected Student 
{
	private:
		int age;
		string addr;
	public:
		void display1( );
};

void Student1::display1( ) 
{
	cout<< "num: "<< num<< endl; //引用基類的保護(hù)成員
	cout<< "name: "<< name<< endl;
	cout<< "sex: "<< sex<< endl;
	cout<< "age: "<< age<< endl;
	cout<< "address: "<< addr<< endl;
}

? 派生類的成員函數(shù)訪問基類的保護(hù)成員是合法的。基類的保護(hù)成員對(duì)派生類的外界來說是不可訪問的(例如,num是基類student的保護(hù)成員,由于派生類是保護(hù)繼承,所以它在派生類中仍受保護(hù),外界不能用stud1.num形式訪問它)對(duì)照【例5.2】可以看到:保護(hù)成員和私有成員的區(qū)別在于把保護(hù)成員的訪問范圍擴(kuò)展到派生類中。

4.多級(jí)派生時(shí)的訪問屬性 (1)介紹

? 以上介紹了只有一級(jí)派生的情況,實(shí)際上常常有多級(jí)派生的情況,如果有圖5.9所示的派生關(guān)系:類A為基類,類B是類A的派生類,類C是類B的派生類,則類C也是類A的派生類。類B是類A的直接派生類,類C是類A的間接派生類。類A是類B的直接基類,是類C的間接基類。

(2)【例5.4】多級(jí)派生類的訪問屬性。如果聲明了以下的了類。
class A 
{             //    基類
	private:
		int ka;
	public:
		int ia;
	protected:
		void fa( );
		int ja;
};

class B: public A 
{         //   public方式
	private:
		int mb;
	public:
		void fb1( );
	protected:
		void fb2( );
};

class C: protected B 
{    //   protected方式
	private:
		int nc;
	public:
		void fc1( );
};

? 類B公有繼承類A,類C保護(hù)繼承類B。各個(gè)成員在不同類中的訪問屬性如下:

五、類型兼容規(guī)則 1.規(guī)則

? 一個(gè)公有派生類的對(duì)象在使用上可以被當(dāng)作基類的對(duì)象,反之則禁止。具體表現(xiàn)在:

  • 派生類的對(duì)象可以被賦值給基類對(duì)象
  • 派生類的對(duì)象可以初始化基類的引用(向下兼容)
  • 指向基類的指針也可以指向派生類
  • 通過基類對(duì)象名、指針只能使用從基類繼承的成員
2.類型兼容規(guī)則舉例
#includeusing namespace std;

class B0 
{	//  基類B0聲明
	public:      //  公有成員函數(shù)

		void display() 
		{
			cout<< "B0::display()"<< endl;
		}
};

class B1: public B0 
{
	public:
		void display() 
		{
			cout<< "B1::display()"<< endl;
		}
};

class D1: public B1 
{
	public:
		void display() 
		{
			cout<< "D1::display()"<< endl;
		}
};

void fun(B0 *ptr) 
{
	ptr->display();	//"對(duì)象指針->成員名"
}

int  main() 
{	//主函數(shù)
	B0 b0;	//聲明B0類對(duì)象
	B1 b1;	//聲明B1類對(duì)象
	D1 d1;	//聲明D1類對(duì)象
	B0 *p;	//聲明B0類指針
	p = &b0;	//  B0類指針指向B0類對(duì)象
	fun(p);
	p = &b1;	//  B0類指針指向B1類對(duì)象
	fun(p);
	p = &d1;	//  B0類指針指向D1類對(duì)象
	fun(p);
	return 0;
}

3.基類與派生類的對(duì)應(yīng)關(guān)系
  • 單繼承:派生類只能從一個(gè)基類派生
  • 多繼承:派生類從多個(gè)基類派生
  • 多重派生:由一個(gè)基類派生出多個(gè)不同的派生類
  • 多層派生:派生類又作為基類,繼續(xù)派生新的類
4.多繼承時(shí)派生類的聲明
class 派生類名:繼承方式1  基類名1,繼承方式2  基類名2,...
{
        成員聲明;
}

【注】每一個(gè)“繼承方式”,只用于限制緊隨其后的基類的繼承

5.多繼承舉例
class A 
{
	public:
		void setA(int);
		void showA();
	private:
		int a;
};

class B 
{
	public:
		void setB(int);
		void showB();
	private:
		int b;
};

class C : public A, private B 
{
	public:
		void setC(int, int, int);
		void showC();
	private:
		int c;
};

void  A::setA(int x) 
{
	a = x;
}

void B::setB(int x) 
{
	b = x;
}

void C::setC(int x, int y, int z) 
{
	//派生類成員直接訪問基類的
	//公有成員
	setA(x);
	setB(y);
	c = z;
}

//其它函數(shù)實(shí)現(xiàn)略
int main() 
{
	C obj;
	obj.setA(5);
	obj.showA();
	obj.setC(6, 7, 9);
	obj.showC();
// obj.setB(6);  錯(cuò)誤
// obj.showB(); 錯(cuò)誤
	return 0;
}
6.繼承與派生的目的
  • 繼承的目的:實(shí)現(xiàn)代碼重用
  • 派生的目的:當(dāng)新的問題出現(xiàn),原有程序無法解決(或不能完全解決)時(shí),需要對(duì)原有程序進(jìn)行改造
六、派生類的構(gòu)造函數(shù)和析構(gòu)函數(shù) 前言——派生類的構(gòu)造函數(shù)?

? 基類的構(gòu)造函數(shù)不被繼承,派生類中需要聲明自己的構(gòu)造函數(shù)。

? 聲明構(gòu)造函數(shù)時(shí),只需要對(duì)本類中新增成員進(jìn)行初始化,調(diào)用基類構(gòu)造函數(shù)對(duì)繼承來的基類成員初始化。

? 派生類的構(gòu)造函數(shù)需要給基類的構(gòu)造函數(shù)傳遞參數(shù)。

1.簡單的派生類的構(gòu)造函數(shù) (1)介紹

? 簡單派生類只有一個(gè)基類,而且只有一級(jí)派生,在派生類的數(shù)據(jù)成員中不包含基類的對(duì)象(即子對(duì)象)。

? 在定義派生類的構(gòu)造函數(shù)時(shí)除了對(duì)自己的數(shù)據(jù)成員進(jìn)行初始化外,還必須用基類的構(gòu)造函數(shù)初始化基類的數(shù)據(jù)成員。構(gòu)造函數(shù)格式如下:

派生類名::派生類名(基類所需的形參,本類成員所需的形參):基類名(基類參數(shù)表)
{
        本類成員初始化賦值語句;
};

? 派生類名后的參數(shù)表分別列出基類和派生類構(gòu)造函數(shù)的形參(有類型和形參變量)。

? 基類參數(shù)表列出傳遞給基類構(gòu)造函數(shù)的實(shí)參,是派生類構(gòu)造函數(shù)總參數(shù)表中的參數(shù)。

? 用派生類構(gòu)造函數(shù)的形參作基類構(gòu)造函數(shù)的實(shí)參。

(2)【例5.5】簡單派生類的構(gòu)造函數(shù)
#include#includeusing namespace std;

class Student 
{                            //聲明基類
	public:                                  //公用部分
		Student(int n, string nam, char s ) 
		{   //基類構(gòu)造函數(shù)
			num = n;
			name = nam;
			sex = s;
		}
		~Student( ) { }
	protected:                               //保護(hù)部分
		int num;
		string name;
		char sex ;                            //基類析構(gòu)函數(shù)
};

class Student1: public Student 
{ //  聲明公用派生類
	public:
		Student1(int n, string nam, char s, int a, char ad[ ] ): Student ( n, nam, s) 
		{ //   派生類構(gòu)造函數(shù)
			age = a;     //  只對(duì)派生類新增的數(shù)據(jù)成員初始化
			addr = ad;
		}
		void show( );
	private:                 //  派生類的私有部分
		int age;
		string addr;
};

void Student1::show() 
{
	cout<< "num: "<< num<< endl;
	cout<< "name: "<< name<< endl;
	cout<< "sex: "<< sex<< endl;
	cout<< "age: "<< age<< endl;
	cout<< "address: "<< addr<< endl;
}

int main( ) 
{
	Student1 stud1(10010, "Wang-li", 'f', 19, "115 Beijing Road, Shanghai");
	Student1 stud2(10011, "Zhang-fun", 'm', 21, "213 Shanghai Road,Beijing");
	stud1.show( );            // 輸出第一個(gè)學(xué)生的數(shù)據(jù)
	stud2.show( );            // 輸出第二個(gè)學(xué)生的數(shù)據(jù)
	return 0;
}

? 在建立一個(gè)對(duì)象時(shí),執(zhí)行構(gòu)造函數(shù)的順序是:派生類構(gòu)造函數(shù)先調(diào)用基類構(gòu)造函數(shù);再執(zhí)行派生類構(gòu)造函數(shù)本身(即派生類構(gòu)造函數(shù)的函數(shù)體)。按上面的例子說,先初始化num,name,sex,然后再初始化age,addr。

? 釋放派生類對(duì)象時(shí),先執(zhí)行派生類析構(gòu)函數(shù),再執(zhí)行其基類的析構(gòu)函數(shù)。

(3)單一繼承時(shí)的構(gòu)造函數(shù)舉例
#includeusing namespace std;

class B 
{
	private:
		int b;
	public:
		B();
		B(int i);
		void Print() const;
};

B::B() 
{
	b = 0;
	cout<< "調(diào)用B的默認(rèn)構(gòu)造函數(shù)."<< endl;
}

B::B(int i) 
{
	b = i;
	cout<< "調(diào)用B的構(gòu)造函數(shù)."<< endl;
}

void B::Print() const 
{
	cout<< b<< endl;
}

class C: public B 
{
	private:
		int c;
	public:
		C();
		C(int i, int j);
		void Print() const;
};

C::C() 
{
	c = 0;
	cout<< "調(diào)用C的默認(rèn)構(gòu)造函數(shù)."<< endl;
}

C::C(int i, int j): B(i) 
{
	c = j;
	cout<< "調(diào)用C的構(gòu)造函數(shù)."<< endl;
}

void C::Print() const 
{
	B::Print();
	cout<< c<< endl;
}

int main() 
{
	C obj(5, 6);
	obj.Print();
	return 0;
}

2.有子對(duì)象的派生類的構(gòu)造函數(shù) (1)介紹

? 類的數(shù)據(jù)成員除了是標(biāo)準(zhǔn)類型或系統(tǒng)提供的類型如string,還可以是類類型,如聲明一個(gè)類時(shí)包含類類型的數(shù)據(jù)成員:Student s1;Student是已聲明過的類名,s1是該類的對(duì)象,我們稱s1為子對(duì)象。以【例5.5】為例,除了可以在派生類student1中增加age、address成員外,還可以增加班長一項(xiàng),而班長本身也是學(xué)生,它屬于student類型,有學(xué)號(hào)和姓名等基本數(shù)據(jù),班長這項(xiàng)就是派生類中的子對(duì)象。

? 怎樣對(duì)子對(duì)象初始化?由于類是一種數(shù)據(jù)類型,不能帶具體的值,何況每個(gè)派生類對(duì)象的子對(duì)象一般是不同的(如學(xué)生A,B,C的班長是A,而學(xué)生D,E,F的班長是F)。所以不能在聲明派生類時(shí)對(duì)子對(duì)象初始化,系統(tǒng)在建立派生類對(duì)象時(shí)調(diào)用派生類構(gòu)造函數(shù)對(duì)子對(duì)象進(jìn)行初始化。

? 派生類構(gòu)造函數(shù)的任務(wù)包括:

  • 對(duì)基類數(shù)據(jù)成員初始化
  • 對(duì)子對(duì)象的數(shù)據(jù)成員初始化
  • 對(duì)派生類的數(shù)據(jù)成員初始化

? 派生類構(gòu)造函數(shù)一般形式為:

派生類名::派生類名 (總參數(shù)表):基類名(實(shí)參表 ), 子對(duì)象名(參數(shù)表)
{
    派生類新增成員的初始化語句;
}

? 執(zhí)行派生類構(gòu)造函數(shù)的順序是:

  • 調(diào)用基類構(gòu)造函數(shù),初始化基類數(shù)據(jù)成員
  • 調(diào)用子對(duì)象構(gòu)造函數(shù),初始化子對(duì)象數(shù)據(jù)成員
  • 執(zhí)行派生類構(gòu)造函數(shù),初始化派生類數(shù)據(jù)成員?

? 編譯系統(tǒng)在此根據(jù)參數(shù)名(而不是參數(shù)的順序)決定各參數(shù)表中參數(shù)之間的傳遞關(guān)系。如果多個(gè)子對(duì)象,要逐個(gè)列出子對(duì)象及其參數(shù)表。

(2)【例】
#include#includeusing namespace std;

class Student 
{                            //聲明基類
	public:                                  //公用部分
		Student(int n, string nam ) 
		{    //基類構(gòu)造函數(shù)
			num = n;
			name = nam;
		}
		void display() 
		{
			cout<< "學(xué)號(hào):"<< num<< endl<< "姓名:"<<  name<< endl;
		}
	protected:                               //保護(hù)部分
		int num;
		string name;
		char sex ;                            //基類析構(gòu)函數(shù)
};

class Student1: public Student 
{ //   public繼承方式
	private:                           //  派生類的私有數(shù)據(jù)
		Student monitor;           //  定義子對(duì)象(班長)
		int age;
		string addr;
	public:
//下面是派生類構(gòu)造函數(shù)
		Student1(int n, string nam, int n1, string nam1, int a, string ad)
			: Student(n, nam), monitor(n1, nam1) 
		{
			age = a;               //    在此處只對(duì)派生類
			addr = ad;            //    新增的數(shù)據(jù)成員初始化
		}


		void show( ) 
		{
			cout<< "這個(gè)學(xué)生是:"<< endl;
			display();            // 輸出num和name
			cout<< "年齡: "<< age<< endl;
			cout<< "地址: "<< addr<< endl<< endl;
		}
//  輸出子對(duì)象的數(shù)據(jù)成員
		void show_monitor() 
		{
			cout<< endl<< "班長是:"<< endl;
			monitor.display();  //調(diào)用基類成員函數(shù)
		}

};

int main( ) 
{
	Student1 stud1(10010, "王力", 10001, "李軍", 19, "上海市北京路115號(hào) ");
	stud1.show( );             //  輸出第一個(gè)學(xué)生的數(shù)據(jù)
	stud1.show_monitor();     //  輸出子對(duì)象的數(shù)據(jù)
	return 0;
}

3.多層派生時(shí)的構(gòu)造函數(shù) (1)介紹

? 一個(gè)類可以派生出一個(gè)派生類,派生類和可以繼續(xù)派生,形成派生的層次結(jié)構(gòu)。多層派生時(shí)怎樣寫派生類的構(gòu)造函數(shù)?現(xiàn)有如圖所示的多層派生類:

? 可以按照前面派生類構(gòu)造函數(shù)的規(guī)則逐層寫出各個(gè)派生類的構(gòu)造函數(shù)。

? 基類的構(gòu)造函數(shù)首部:

Student(int n, string nam );

派生類student1的構(gòu)造函數(shù)首部:

Student1(int n,string nam,int a):Student(n,nam);

? 派生類student2的構(gòu)造函數(shù)首部:

Student2(int n,string nam,int a,int s):Student1(n,nam,a);

寫派生類構(gòu)造函數(shù)的規(guī)則是:只須調(diào)用其直接基類的構(gòu)造函數(shù)即可,不要列出每一層派生類的構(gòu)造函數(shù)。在聲明Student2類對(duì)象時(shí),調(diào)用Student2構(gòu)造函數(shù),在執(zhí)行Student2構(gòu)造函數(shù)時(shí),先調(diào)用Student1構(gòu)造函數(shù),在執(zhí)行Student1構(gòu)造函數(shù)時(shí),先調(diào)用基類Student構(gòu)造函數(shù)。初始化的順序是:

  • 先初始化基類的數(shù)據(jù)成員num和name
  • 再初始化Student1的數(shù)據(jù)成員age
  • 最后初始化Student2的數(shù)據(jù)成員score
(2)舉例
#include#includeusing namespace std;

class Student 
{                            //聲明基類
	public:                                  //公用部分
		Student(int n, string nam ) 
		{          //基類構(gòu)造函數(shù)
			num = n;
			name = nam;
		}
		void display() 
		{                         //輸出基類數(shù)據(jù)成員
			cout<< "num:"<< num<< endl;
			cout<< "name:"<< name<< endl;
		}
	protected:                                //保護(hù)部分
		int num;                                //基類有兩個(gè)數(shù)據(jù)成員
		string name;
};

class Student1: public Student 
{ //聲明公用派生類Student1
	public:
		Student1(int n, string nam, int a): Student(n, nam)
//派生類構(gòu)造函數(shù)
		{
			age = a;    //在此處只對(duì)派生類新增的數(shù)據(jù)成員初始化
		}
		void show( ) 
		{                 //輸出num,name和age
			display();                      //輸出num和name
			cout<< "age: "<< age<< endl;
		}
	private:                                   //派生類的私有數(shù)據(jù)
		int age;                                  //增加一個(gè)數(shù)據(jù)成員
};

class Student2: public Student1

//聲明間接公用派生類student2
{
	public:
		//下面是間接派生類構(gòu)造函數(shù)
		Student2(int n, string nam, int a, int s): Student1(n, nam, a) 
		{
			score = s;
		}
		void show_all() 
		{   //  輸出全部數(shù)據(jù)成員
			show();               //  輸出num和name
			cout<< "score:"<< score<< endl; //輸出age
		}
	private:
		int score;                                   //增加一個(gè)數(shù)據(jù)成員
};

int main( ) 
{
	Student2 stud(10010, "李明", 17, 89);
	stud.show_all( );  //輸出學(xué)生的全部數(shù)據(jù)
	return 0;
}

4.派生類構(gòu)造函數(shù)的特殊形式

(1)當(dāng)不需要對(duì)派生類新增成員進(jìn)行初始化時(shí),派生類構(gòu)造函數(shù)的函數(shù)體可以為空。如【例5.6】程序中派生類Student1的構(gòu)造函數(shù)改寫成:

Student1(int n,string nam,int n1,string nam1 ) : Student(n,nam),monitor(n1,nam1)

? 在調(diào)用派生類構(gòu)造函數(shù)時(shí)不對(duì)派生類的數(shù)據(jù)成員初始化。

(2)如果在基類里沒有定義構(gòu)造函數(shù),或定義了沒有參數(shù)的構(gòu)造函數(shù),在定義派生類構(gòu)造函數(shù)時(shí)可以不寫基類的構(gòu)造函數(shù)。因?yàn)榇藭r(shí)派生類構(gòu)造函數(shù)沒有向基類構(gòu)造函數(shù)傳遞參數(shù)的任務(wù)。在調(diào)用派生類構(gòu)造函數(shù)時(shí),系統(tǒng)地自動(dòng)首先調(diào)用基類的默認(rèn)構(gòu)造函數(shù)。

(3) 如果在基類和子對(duì)象的類中都沒有定義帶參數(shù)的構(gòu)造函數(shù),也不需要對(duì)派生類自己的數(shù)據(jù)成員進(jìn)行初始化,可以不定義派生類的構(gòu)造函數(shù)

(4)如果在基類或子對(duì)象的類聲明里定義了帶參數(shù)的構(gòu)造函數(shù),就必須定義派生類構(gòu)造函數(shù),并在派生類構(gòu)造函數(shù)中寫出基類或子對(duì)象類的構(gòu)造函數(shù)及其參數(shù)表

(5)如果在基類既定義了無參數(shù)的構(gòu)造函數(shù)也定義了有參數(shù)的構(gòu)造函數(shù),在定義派生類構(gòu)造函數(shù)時(shí),既可以包含基類構(gòu)造函數(shù)及其參數(shù),也可以不包含基類構(gòu)造函數(shù)

5.派生類的析構(gòu)函數(shù) (1)介紹

? 類派生時(shí),派生類不能繼承基類的析構(gòu)函數(shù),撤銷派生類對(duì)象時(shí),需要派生類的析構(gòu)函數(shù)去調(diào)用基類的析構(gòu)函數(shù)。首先執(zhí)行派生類自己的析構(gòu)函數(shù),清理派生類新增加的成員,然后調(diào)用子對(duì)象類的析構(gòu)函數(shù)清理子對(duì)象,最后調(diào)用基類析構(gòu)函數(shù)清理基類的成員。

(2)單一繼承時(shí)構(gòu)造函數(shù)、析構(gòu)函數(shù)舉例
#includeusing namespace std;

class B 
{
	private:
		int b;
	public:
		B();
		B(int i);
		~B();
		void Print() const;
};

B::B() 
{
	b = 0;
	cout<< "調(diào)用B的默認(rèn)構(gòu)造函數(shù)."<< endl;
}

B::B(int i) 
{
	b = i;
	cout<< "調(diào)用B的構(gòu)造函數(shù)."<< endl;
}

B::~B() 
{
	cout<< "調(diào)用B的析構(gòu)函數(shù)."<< endl;
}

void B::Print() const 
{
	cout<< b<< endl;
}

class C: public B 
{
	private:
		int c;
	public:
		C();
		C(int i, int j);
		~C();
		void Print() const;
};

C::C() 
{
	c = 0;
	cout<< "調(diào)用C的默認(rèn)構(gòu)造函數(shù)."<< endl;
}

C::C(int i, int j): B(i) 
{
	c = j;
	cout<< "調(diào)用C的構(gòu)造函數(shù)."<< endl;
}

C::~C() 
{
	cout<< "調(diào)用C的析構(gòu)函數(shù)."<< endl;
}

void C::Print() const 
{
	B::Print();
	cout<< c<< endl;
}

int main() 
{
	C obj(5, 6);
	obj.Print();
	return 0;
}

七、多重繼承 1.聲明多重繼承的方法 (1)介紹

? 假定已聲明了類A,類B和類C,由它們派生出新類D,聲明的形式可以是:

Class D: public A,private B, protected C
	{  D類新增的成員聲明 }

? 多重繼承派生類的構(gòu)造函數(shù)在初始化表中包含多個(gè)基類構(gòu)造函數(shù),假定派生類有三個(gè)基類,它的構(gòu)造函數(shù)形式是:

派生類構(gòu)造函數(shù)名(總參數(shù)表):基類1構(gòu)造函數(shù)(參數(shù)表),基類2構(gòu)造函數(shù)(參數(shù)表),基類3構(gòu)造函數(shù)(參數(shù)表)
   { 派生類新增成員初始化語句 }

? 各基類的排列順序不分先后,系統(tǒng)調(diào)用基類構(gòu)造函數(shù)的順序就是聲明派生類時(shí)基類的出現(xiàn)順序。如在前面中聲明派生類D時(shí),基類出現(xiàn)的順序是A,B,C。系統(tǒng)先調(diào)用A的構(gòu)造函數(shù),再掉用B的構(gòu)造函數(shù),最后調(diào)用C的構(gòu)造函數(shù)。

(2)【例5.8】

聲明一個(gè)教師類和一個(gè)學(xué)生類,用多重繼承的方式聲明一個(gè)研究生類。教師包括name,age,title數(shù)據(jù)成員,學(xué)生類包括name1,sex,score。在定義派生類對(duì)象時(shí)給出初始化數(shù)據(jù),輸出這些數(shù)據(jù)。

#include#includeusing namespace std;

class Teacher 
{                      //  聲明Teacher(教師)類
	public:                                  //  公用部分
		Teacher(string nam, int a, string t) 
		{  //  構(gòu)造函數(shù)
			name = nam;
			age = a;
			title = t;
		}
		void display() 
		{                        //  輸出教師有關(guān)數(shù)據(jù)
			cout<< "name:"<< name<< endl;
			cout<< "age"<< age<< endl;
			cout<< "title:"<< title<< endl;
		}
	protected:                               //  保護(hù)部分
		string name;
		int age;
		string title;                           //  職稱
};

class Student 
{                          //  聲明類Student(學(xué)生)
	public:
		Student(string nam, char s, float sco) 
		{
			name1 = nam;
			sex = s;
			score = sco;
		}                         //  構(gòu)造函數(shù)
		void display1() 
		{                     //  輸出學(xué)生有關(guān)數(shù)據(jù)
			cout<< "name:"<< name1<< endl;
			cout<< "sex:"<< sex<< endl;
			cout<< "score:"<< score<< endl;
		}
	protected:                               //  保護(hù)部分
		string name1;
		char sex;
		float score;                            //  成績
};

class Graduate: public Teacher, public Student 
{
	public:
		Graduate(string nam, int a, char s, string t, float sco, float w):
			Teacher(nam, a, t), Student(nam, s, sco), wage(w) {}
		void show( ) 
		{                               //  輸出人員的有關(guān)數(shù)據(jù)
			cout<< "name:"<< name<< endl;
			cout<< "age:"<< age<< endl;
			cout<< "sex:"<< sex<< endl;
			cout<< "score:"<< score<< endl;
			cout<< "title:"<< title<< endl;
			cout<< "wages:"<< wage<< endl;
		}
	private:
		float wage;                                  //  工資
};

int main( ) 
{
	Graduate grad1("Wang-li", 24, 'f', "assistant", 89.5, 1234.5);
	grad1.show( );
	return 0;
}

【注】從這個(gè)程序中可以發(fā)現(xiàn),在多重繼承時(shí),從不同的基類中會(huì)繼承重復(fù)的數(shù)據(jù)成員,例如本例中姓名就是重復(fù)的數(shù)據(jù)成員。?

2.多重繼承派生類的構(gòu)造函數(shù) (1)派生類構(gòu)造函數(shù)舉例
#includeusing namespace std;

class B1 
{	//基類B1,構(gòu)造函數(shù)有參數(shù)
	public:
		B1(int i) 
		{
			cout<< "構(gòu)造 B1 "<< i<< endl;
		}
};

class B2 
{	//基類B2,構(gòu)造函數(shù)有參數(shù)
	public:
		B2(int j) 
		{
			cout<< "構(gòu)造 B2 "<< j<< endl;
		}
};

class B3 
{	//基類B3,構(gòu)造函數(shù)無參數(shù)
	public:
		B3() 
		{
			cout<< "構(gòu)造 B3 *"<< endl;
		}
};

class C: public B2, public B1, public B3 
{
	public:	//派生類的公有成員
		C(int a, int b, int c, int d):
			B1(a), B2(b), memberB1(c), memberB2(d)  {}
	private:	//派生類的私有對(duì)象成員
		B1 memberB1;
		B2 memberB2;
		B3 memberB3;
};

int main() 
{
	C obj(1, 2, 3, 4);
	return 0;
}

【注】從結(jié)果看到多重繼承時(shí),系統(tǒng)先調(diào)用基類的構(gòu)造函數(shù),再掉用子對(duì)象的構(gòu)造函數(shù),最后調(diào)用派生類的構(gòu)造函數(shù)。

(2)同名隱藏規(guī)則

當(dāng)派生類與基類中有相同成員時(shí):

  • 若未強(qiáng)行指明,則通過派生類對(duì)象使用的是派生類中的同名成員
  • 如要通過派生類對(duì)象訪問基類中被覆蓋的同名成員,應(yīng)使用基類名限定
(3)多繼承同名隱藏舉例
#includeusing namespace std;

class B1 
{	//聲明基類B1
	public:	//外部接口
		int nV;
		void fun()  
		{
			cout<< "Member of B1"<< endl;
		}
};

class B2 
{	//聲明基類B2
	public:	//外部接口
		int nV;
		void fun() 
		{
			cout<< "Member of B2"<< endl;
		}
};

class D1: public B1, public B2 
{
	public:
		int nV;	//同名數(shù)據(jù)成員
		void fun() 
		{
			cout<< "Member of D1"<< endl;   //同名函數(shù)成員
		}
};

int main() 
{
	D1 d1;
	d1.nV = 1; //對(duì)象名.成員名標(biāo)識(shí), 訪問D1類成員
	d1.fun();

	d1.B1::nV = 2;	//作用域分辨符標(biāo)識(shí), 訪問基類B1成員
	d1.B1::fun();

	d1.B2::nV = 3;	//作用域分辨符標(biāo)識(shí), 訪問基類B2成員
	d1.B2::fun();
	return 0;
}

3.多重繼承引起的二義性問題 (1)介紹

? 多繼承最常見的問題是派生類繼承基類同名成員而產(chǎn)生的二義性問題。

? 在多重繼承時(shí),基類與派生類之間,或基類之間出現(xiàn)同名成員時(shí),將出現(xiàn)訪問時(shí)的二義性(不確定性)——采用虛函數(shù)或同名隱藏規(guī)則來解決。

? 當(dāng)派生類從多個(gè)基類派生,而這些基類又從同一個(gè)基類派生,則在訪問此共同基類中的成員時(shí),將產(chǎn)生二義性——采用虛基類來解決。

(2)二義性問題舉例(一)
class A
{
    public:
        void  f();
};
class B
{
    public:
        void f();
        void g()
};
class C: public A, piblic B
{         
    public:
           void g();
           void h();
};

? 如果聲明:C c1;則c1.f()具有二義性,而c1.g()無二義性(同名覆蓋原則)

(3)二義性的解決方法
  • 解決方法一:用類名來限定c1.A::f()或c1.B::f()
  • 解決方法二:同名覆蓋。在C中聲明一個(gè)同名成員f(),f()再根據(jù)需要調(diào)用A::f()或B::f()
(4)二義性問題舉例(二)?
#includeusing namespace std;

class B 
{
	public:
		B(int i ) 
		{
			b = i;
		}
		int b;
};

class B1 : public B 
{
	public:
		B1(int b, int bx): B(b) 
		{
			b1 = bx;
		}
	private:
		int b1;
};

class B2 : public B 
{
	public:
		B2(int b, int bx): B(b) 
		{
			b2 = bx;
		}
	private:
		int b2;
};

class C: public B1, public B2 
{
	public:
		C(int x1, int x2, int x3, int x4): B1(x1, x2), B2(x1, x3) 
		{
			d = x4;
		}
	private:
		int d;
};

int main(int argc, char *argv[]) 
{
	C cc(1, 2, 3, 4);
	cout<< cc.B1::b<< endl;
	cout<< cc.B2::b<< endl;
	//cout<

? 派生類C的對(duì)象的存儲(chǔ)結(jié)構(gòu)示意圖:

//有二義性
C cc;
cc.b;
cc.B::b;
//無二義性
cc.B1::b;
cc.B2::b;
(5)多重繼承的同名問題

? 如果類A和類B都有成員函數(shù)display和數(shù)據(jù)成員a,類c是類A和類B的直接派生類。分別討論下下買你的三種情況:

  • 兩個(gè)基類有同名成員,如上圖所示
Class  A 
{
	public:
		int a;
		void display( );
};

Class  B 
{
	public:
		int a;
		void display( );
};
Class  C :public A, public B 
{
	public:
		int b;
		void show( );
};

? 如果在main函數(shù)中定義C類對(duì)象c1,并寫出如下語句:

C c1;
c1.a=3;
c1.display();

? 由于基類A和基類B都有數(shù)據(jù)成員a和成員函數(shù)display,系統(tǒng)無法辨別要訪問的是A類還是B類,程序編譯報(bào)錯(cuò)。解決這個(gè)問題可以用基類名限定,如:

c1.A::a=3;
c1.A::display();

? 如果在派生類C中通過派生類成員函數(shù)show訪問A的display和a,可以這樣寫:

A::a=3;
A::display();

為了清楚起見,上圖應(yīng)該用下圖的形式表示:

  • 兩個(gè)基類和派生類三者都有同名成員。將前面的C類聲明改為:
Class  C : public A, public B
{ 
	public:
		int a;
		void display( );
};

? 如果在main函數(shù)中定義C類對(duì)象c1:

C c1;
c1.a=3;
c1.display();

? 程序可以通過編譯,也能正常運(yùn)行,在語法上認(rèn)為這樣訪問的是派生類的成員a和成員函數(shù)display,規(guī)則是:派生類屏蔽基類的同名成員。對(duì)于帶參數(shù)的成員函數(shù)除了要函數(shù)名相同外,參數(shù)的個(gè)數(shù)和類型都要相同才符合屏蔽條件。如果在派生類外訪問基類A的成員,要指明作用域A:。

c1.A::a=3;
c1.A::display();
  • 如果類A和類B又是從同一個(gè)基類派生的:
Class N 
{
	public :
		int a;
		Void display()
		{ 
			cout<<"N::a="<

? 類A和類B分貝從類N繼承了數(shù)據(jù)成員a和成員函數(shù)display,在類A和類B中存在同名數(shù)據(jù)成員a和成員函數(shù)display。類A和類B中的同名數(shù)據(jù)成員a分別為不同的內(nèi)存單元。在程序中類A和類B的構(gòu)造函數(shù)調(diào)用基類N的構(gòu)造函數(shù)分別對(duì)類A和類B的數(shù)據(jù)成員a初始化。對(duì)象c1怎樣訪問類A從基類N繼承來的成員呢?訪問格式如下:

c1.A::a=3;
c1.A::display();

你是否還在尋找穩(wěn)定的海外服務(wù)器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機(jī)房具備T級(jí)流量清洗系統(tǒng)配攻擊溯源,準(zhǔn)確流量調(diào)度確保服務(wù)器高可用性,企業(yè)級(jí)服務(wù)器適合批量采購,新人活動(dòng)首月15元起,快前往官網(wǎng)查看詳情吧

當(dāng)前標(biāo)題:【C++面向?qū)ο蟪绦蛟O(shè)計(jì)】CH5繼承與派生-創(chuàng)新互聯(lián)
文章URL:http://aaarwkj.com/article32/icspc.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供小程序開發(fā)用戶體驗(yàn)、移動(dòng)網(wǎng)站建設(shè)品牌網(wǎng)站制作、電子商務(wù)、靜態(tài)網(wǎng)站

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

高清中文字幕一区二区三区| 五月婷婷六月丁香伊人妞| 欧美午夜激情片在线观看| 国产一区二区精品久久岳| 国产剧情av一区在线观看| 美女高潮久久久777| 国产av剧情精品亚洲| 四季一区二区三区av| 日本在线人妻一区二区| 一本色道久久亚洲综合精品蜜桃| 免费黄色一区二区三区| 婷婷网色偷偷亚洲男人| 亚洲国产传媒在线观看| 亚洲免费成人一区二区| 亚洲av毛片一区二区三区网| 日韩黄片一区二区三区| 国产精品中文一区二区三区| 欧美 成人一区二区三区| 99久久中文字幕伊人| 欧美在线观看日韩精品| 国产高清亚洲精品视频| 天堂在线av免费观看| 91福利免费在线看| 日韩高清av不卡一区二区三区 | 黄色av免费播放网站| 亚洲 综合 久久久| 成人爱爱视频在线免费观看| 日韩精品国产专区一区| 日本sm视频在线观看| 久久婷婷精品国产亚洲av| 日本成人一区二区三区在线| 国产午夜男人天堂手机| 小仙女精品经典三级永久| 亚洲欧美日韩精品区| 久久成人a毛片免费观看网站| 久久综合中文字幕一区| 欧美日本午夜福利在线观看| 日韩欧美国产亚洲在线| 日本免费精品一区二区三区四区 | 性生活视频在线观看免费| 亚洲免费av一区在线观看|