C++:C++繼承與多態(tài)技術(shù)教程_第1頁
C++:C++繼承與多態(tài)技術(shù)教程_第2頁
C++:C++繼承與多態(tài)技術(shù)教程_第3頁
C++:C++繼承與多態(tài)技術(shù)教程_第4頁
C++:C++繼承與多態(tài)技術(shù)教程_第5頁
已閱讀5頁,還剩8頁未讀 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡介

C++:C++繼承與多態(tài)技術(shù)教程1C++繼承基礎(chǔ)1.1C++類與對象基礎(chǔ)回顧在C++中,類是面向?qū)ο缶幊痰幕緲?gòu)建塊,它允許我們定義自己的數(shù)據(jù)類型,這個(gè)數(shù)據(jù)類型可以包含數(shù)據(jù)成員和成員函數(shù)。數(shù)據(jù)成員用于存儲數(shù)據(jù),而成員函數(shù)用于處理這些數(shù)據(jù)。對象是類的實(shí)例,每個(gè)對象都有自己的狀態(tài)和行為。例如,我們可以定義一個(gè)Person類,它包含姓名和年齡兩個(gè)數(shù)據(jù)成員,以及一個(gè)顯示個(gè)人信息的成員函數(shù)。classPerson{

private:

std::stringname;

intage;

public:

//構(gòu)造函數(shù)

Person(std::stringn,inta):name(n),age(a){}

//成員函數(shù)

voiddisplayInfo(){

std::cout<<"Name:"<<name<<",Age:"<<age<<std::endl;

}

};

//創(chuàng)建Person對象

Personp("Alice",30);

p.displayInfo();//輸出:Name:Alice,Age:301.2單繼承與多繼承概念1.2.1單繼承單繼承是指一個(gè)類直接繼承自另一個(gè)類。子類可以訪問父類的公有和受保護(hù)成員,但不能訪問私有成員。子類可以重寫父類的成員函數(shù),以提供不同的實(shí)現(xiàn)。例如,我們可以定義一個(gè)Student類,它繼承自Person類,并添加一個(gè)grade數(shù)據(jù)成員。classStudent:publicPerson{

private:

intgrade;

public:

//構(gòu)造函數(shù)

Student(std::stringn,inta,intg):Person(n,a),grade(g){}

//成員函數(shù)

voiddisplayInfo(){

Person::displayInfo();

std::cout<<"Grade:"<<grade<<std::endl;

}

};

//創(chuàng)建Student對象

Students("Bob",20,12);

s.displayInfo();//輸出:Name:Bob,Age:20,Grade:121.2.2多繼承多繼承是指一個(gè)類可以繼承自多個(gè)基類。在C++中,這允許子類訪問和使用多個(gè)基類的特性。然而,多繼承可能導(dǎo)致“菱形問題”,即當(dāng)一個(gè)類從兩個(gè)基類繼承,而這兩個(gè)基類又從同一個(gè)基類繼承時(shí),子類可能會接收到基類的多個(gè)實(shí)例。例如,我們可以定義一個(gè)Teacher類,它繼承自Person類和Subject類。classSubject{

public:

std::stringsubjectName;

Subject(std::stringname):subjectName(name){}

};

classTeacher:publicPerson,publicSubject{

public:

Teacher(std::stringn,inta,std::strings):Person(n,a),Subject(s){}

voiddisplayInfo(){

Person::displayInfo();

std::cout<<"Subject:"<<subjectName<<std::endl;

}

};

//創(chuàng)建Teacher對象

Teachert("Carol",40,"Math");

t.displayInfo();//輸出:Name:Carol,Age:40,Subject:Math1.3繼承中的訪問控制在C++中,基類的成員在派生類中的訪問性取決于繼承方式和成員的訪問控制屬性。有三種繼承方式:公有繼承(public)、受保護(hù)繼承(protected)和私有繼承(private)。公有繼承:基類的公有和受保護(hù)成員在派生類中保持相同的訪問性。受保護(hù)繼承:基類的公有成員在派生類中變?yōu)槭鼙Wo(hù)成員,受保護(hù)成員保持受保護(hù)。私有繼承:基類的所有成員在派生類中變?yōu)樗接谐蓡T。例如,我們定義一個(gè)Employee類,它公有繼承自Person類,并添加一個(gè)私有數(shù)據(jù)成員salary。classEmployee:publicPerson{

private:

doublesalary;

public:

//構(gòu)造函數(shù)

Employee(std::stringn,inta,doubles):Person(n,a),salary(s){}

//成員函數(shù)

voiddisplayInfo(){

Person::displayInfo();

std::cout<<"Salary:"<<salary<<std::endl;

}

};在這個(gè)例子中,Employee類可以訪問Person類的公有和受保護(hù)成員,但Person類的私有成員對Employee類不可見。1.4構(gòu)造函數(shù)與析構(gòu)函數(shù)在繼承中的作用在繼承中,構(gòu)造函數(shù)和析構(gòu)函數(shù)的正確使用至關(guān)重要。子類的構(gòu)造函數(shù)必須調(diào)用基類的構(gòu)造函數(shù)來初始化基類的數(shù)據(jù)成員。同樣,析構(gòu)函數(shù)的順序也必須正確,以確?;惖馁Y源在子類的資源之前被釋放。例如,我們定義一個(gè)Manager類,它繼承自Employee類,并添加一個(gè)teamSize數(shù)據(jù)成員。classManager:publicEmployee{

private:

intteamSize;

public:

//構(gòu)造函數(shù)

Manager(std::stringn,inta,doubles,intts):Employee(n,a,s),teamSize(ts){}

//析構(gòu)函數(shù)

~Manager(){

//釋放Manager特有的資源

}

//成員函數(shù)

voiddisplayInfo(){

Employee::displayInfo();

std::cout<<"TeamSize:"<<teamSize<<std::endl;

}

};在這個(gè)例子中,Manager類的構(gòu)造函數(shù)首先調(diào)用Employee類的構(gòu)造函數(shù)來初始化Person類和Employee類的數(shù)據(jù)成員,然后初始化Manager類特有的數(shù)據(jù)成員teamSize。析構(gòu)函數(shù)的順序則相反,Manager類的析構(gòu)函數(shù)先釋放Manager特有的資源,然后Employee類的析構(gòu)函數(shù)被調(diào)用,最后Person類的析構(gòu)函數(shù)被調(diào)用。通過上述示例,我們回顧了C++中的類與對象基礎(chǔ),理解了單繼承和多繼承的概念,探討了繼承中的訪問控制機(jī)制,以及構(gòu)造函數(shù)和析構(gòu)函數(shù)在繼承中的作用。這些是C++面向?qū)ο缶幊讨胁豢苫蛉钡牟糠?,掌握它們對于編寫?fù)雜和可維護(hù)的代碼至關(guān)重要。2C++多態(tài)深入2.1虛函數(shù)與抽象類詳解在C++中,虛函數(shù)是實(shí)現(xiàn)運(yùn)行時(shí)多態(tài)的關(guān)鍵。當(dāng)一個(gè)類的成員函數(shù)被聲明為虛函數(shù)時(shí),它允許該函數(shù)在派生類中被重寫,從而在運(yùn)行時(shí)根據(jù)對象的實(shí)際類型調(diào)用相應(yīng)的函數(shù)版本。虛函數(shù)的聲明使用virtual關(guān)鍵字。2.1.1示例代碼#include<iostream>

//抽象基類

classAnimal{

public:

virtualvoidmakeSound()const=0;//純虛函數(shù)

virtual~Animal(){}//虛析構(gòu)函數(shù)

};

//派生類

classDog:publicAnimal{

public:

voidmakeSound()constoverride{

std::cout<<"Woof!"<<std::endl;

}

};

classCat:publicAnimal{

public:

voidmakeSound()constoverride{

std::cout<<"Meow!"<<std::endl;

}

};

intmain(){

Animal*animal1=newDog();

Animal*animal2=newCat();

animal1->makeSound();//輸出"Woof!"

animal2->makeSound();//輸出"Meow!"

deleteanimal1;

deleteanimal2;

return0;

}2.1.2解釋在這個(gè)例子中,Animal類是一個(gè)抽象類,因?yàn)樗艘粋€(gè)純虛函數(shù)makeSound()。抽象類不能被實(shí)例化,但可以被繼承。Dog和Cat類分別繼承自Animal類,并實(shí)現(xiàn)了makeSound()函數(shù)。通過基類指針調(diào)用makeSound()時(shí),會根據(jù)指針實(shí)際指向的對象類型調(diào)用相應(yīng)的函數(shù)版本,這就是運(yùn)行時(shí)多態(tài)。2.2運(yùn)行時(shí)多態(tài)與編譯時(shí)多態(tài)的區(qū)別運(yùn)行時(shí)多態(tài)和編譯時(shí)多態(tài)是C++中多態(tài)的兩種形式。運(yùn)行時(shí)多態(tài)通過虛函數(shù)實(shí)現(xiàn),而編譯時(shí)多態(tài)則通過函數(shù)重載和模板實(shí)現(xiàn)。2.2.1運(yùn)行時(shí)多態(tài)示例#include<iostream>

classBase{

public:

virtualvoidprint()const{

std::cout<<"Base"<<std::endl;

}

};

classDerived:publicBase{

public:

voidprint()constoverride{

std::cout<<"Derived"<<std::endl;

}

};

intmain(){

Base*basePtr=newDerived();

basePtr->print();//輸出"Derived"

deletebasePtr;

return0;

}2.2.2編譯時(shí)多態(tài)示例#include<iostream>

voidprint(intx){

std::cout<<"Integer:"<<x<<std::endl;

}

voidprint(doublex){

std::cout<<"Double:"<<x<<std::endl;

}

intmain(){

inti=10;

doubled=10.5;

print(i);//輸出"Integer:10"

print(d);//輸出"Double:10.5"

return0;

}2.2.3解釋運(yùn)行時(shí)多態(tài)允許在程序運(yùn)行時(shí)動態(tài)地確定調(diào)用哪個(gè)函數(shù)版本,而編譯時(shí)多態(tài)則在編譯時(shí)就已經(jīng)確定了調(diào)用的函數(shù)版本。運(yùn)行時(shí)多態(tài)需要虛函數(shù)表的支持,而編譯時(shí)多態(tài)則通過函數(shù)重載或模板在編譯時(shí)解析。2.3多態(tài)中的動態(tài)綁定動態(tài)綁定是實(shí)現(xiàn)運(yùn)行時(shí)多態(tài)的機(jī)制。當(dāng)一個(gè)虛函數(shù)被調(diào)用時(shí),C++運(yùn)行時(shí)系統(tǒng)會查找實(shí)際對象的虛函數(shù)表,從而調(diào)用正確的函數(shù)版本。這種查找和調(diào)用過程是在程序運(yùn)行時(shí)動態(tài)進(jìn)行的,因此稱為動態(tài)綁定。2.3.1示例代碼#include<iostream>

classBase{

public:

virtualvoidprint()const{

std::cout<<"Base"<<std::endl;

}

};

classDerived:publicBase{

public:

voidprint()constoverride{

std::cout<<"Derived"<<std::endl;

}

};

intmain(){

Base*basePtr=newDerived();

basePtr->print();//輸出"Derived"

deletebasePtr;

return0;

}2.3.2解釋在這個(gè)例子中,basePtr是一個(gè)指向Derived對象的Base類指針。當(dāng)通過basePtr調(diào)用print()函數(shù)時(shí),C++運(yùn)行時(shí)系統(tǒng)會查找Derived對象的虛函數(shù)表,從而調(diào)用Derived類的print()函數(shù),而不是Base類的print()函數(shù)。2.4使用多態(tài)進(jìn)行代碼設(shè)計(jì)與擴(kuò)展多態(tài)不僅是一種語言特性,也是一種設(shè)計(jì)模式,它允許我們編寫更加靈活和可擴(kuò)展的代碼。通過定義一個(gè)抽象基類和多個(gè)派生類,我們可以創(chuàng)建一個(gè)函數(shù)或?qū)ο螅軌蛱幚聿煌愋偷呐缮悓ο?,而無需知道具體類型。2.4.1示例代碼#include<iostream>

#include<vector>

classShape{

public:

virtualdoublearea()const=0;//純虛函數(shù)

virtual~Shape(){}//虛析構(gòu)函數(shù)

};

classCircle:publicShape{

doubleradius;

public:

Circle(doubler):radius(r){}

doublearea()constoverride{

return3.14159*radius*radius;

}

};

classRectangle:publicShape{

doublewidth,height;

public:

Rectangle(doublew,doubleh):width(w),height(h){}

doublearea()constoverride{

returnwidth*height;

}

};

voidprintArea(constShape&shape){

std::cout<<"Area:"<<shape.area()<<std::endl;

}

intmain(){

std::vector<Shape*>shapes;

shapes.push_back(newCircle(5));

shapes.push_back(newRectangle(4,6));

for(constauto&shape:shapes){

printArea(*shape);//輸出每個(gè)形狀的面積

}

for(auto&shape:shapes){

deleteshape;

}

return0;

}2.4.2解釋在這個(gè)例子中,Shape是一個(gè)抽象基類,它定義了一個(gè)純虛函數(shù)area()。Circle和Rectangle類分別繼承自Shape類,并實(shí)現(xiàn)了area()函數(shù)。我們創(chuàng)建了一個(gè)Shape指針的vector,并添加了Circle和Rectangle對象。通過printArea()函數(shù),我們可以調(diào)用每個(gè)形狀的area()函數(shù),而無需知道具體形狀類型。這種設(shè)計(jì)使得代碼更加靈活,易于擴(kuò)展新的形狀類型。3高級主題與實(shí)踐3.1虛繼承與鉆石問題解決在C++中,當(dāng)一個(gè)類從多個(gè)基類繼承,而這些基類又有一個(gè)共同的基類時(shí),就會出現(xiàn)所謂的“鉆石問題”。虛繼承是用來解決這個(gè)問題的一種機(jī)制。3.1.1原理虛繼承確保了在派生類中,即使有多個(gè)基類繼承自同一個(gè)類,也只會創(chuàng)建一個(gè)基類的實(shí)例。這避免了多個(gè)實(shí)例的沖突,從而解決了鉆石問題。3.1.2示例//虛繼承解決鉆石問題

#include<iostream>

classA{

public:

intx;

A():x(1){}

};

classB:virtualpublicA{

public:

B():A(),x(2){}

};

classC:virtualpublicA{

public:

C():A(),x(3){}

};

classD:publicB,publicC{

public:

D():x(4){

std::cout<<"D的x值:"<<x<<std::endl;//輸出D的x值:4

}

};

intmain(){

Dd;

return0;

}在這個(gè)例子中,D類從B和C類繼承,而B和C又都從A類虛繼承。這樣,D類中只存在一個(gè)A類的實(shí)例,避免了鉆石問題。3.2多態(tài)與模板的結(jié)合使用多態(tài)和模板是C++中兩個(gè)強(qiáng)大的特性,它們可以結(jié)合使用,以實(shí)現(xiàn)更靈活和通用的代碼設(shè)計(jì)。3.2.1原理通過使用虛函數(shù)和模板,可以在運(yùn)行時(shí)根據(jù)對象的實(shí)際類型來調(diào)用相應(yīng)的函數(shù),同時(shí)保持代碼的通用性。3.2.2示例//多態(tài)與模板結(jié)合使用

#include<iostream>

template<typenameT>

classBase{

public:

virtualvoidprint()const{

std::cout<<"Baseprint"<<std::endl;

}

};

template<typenameT>

classDerived:publicBase<T>{

public:

voidprint()constoverride{

std::cout<<"Derivedprint"<<std::endl;

}

};

intmain(){

Base<int>*base=newDerived<int>();

base->print();//輸出Derivedprint

deletebase;

return0;

}在這個(gè)例子中,Base和Derived都是模板類,Derived繼承自Base。通過指針base調(diào)用print函數(shù),可以實(shí)現(xiàn)多態(tài),即根據(jù)實(shí)際對象類型調(diào)用相應(yīng)的函數(shù)。3.3C++11/14/17中多態(tài)的新特性C++11、C++14和C++17引入了一些新特性,這些特性增強(qiáng)了多態(tài)的使用和靈活性。3.3.1原理新特性包括右值引用、override和final關(guān)鍵字、通用lambda表達(dá)式等,這些都可以在多態(tài)的上下文中使用,以實(shí)現(xiàn)更安全、更簡潔的代碼。3.3.2示例//使用C++11特性增強(qiáng)多態(tài)

#include<iostream>

#include<functional>

classBase{

public:

virtualvoidprint()const=0;

virtual~Base(){}

};

classDerived:publicBase{

public:

voidprint()constoverride{

std::cout<<"Derivedprint"<<std::endl;

}

};

intmain(){

std::function<void(Base*)>func=[](Base*base){

base->print();

};

Derivedd;

func(&d);//輸出Derivedprint

return0;

}在這個(gè)例子中,使用了C++11的std::function和lambda表達(dá)式,以及override關(guān)鍵字。std::function允許我們以類型安全的方式存儲和調(diào)用函數(shù),而lambda表達(dá)式則提供了簡潔的函數(shù)定義方式。3.4面向?qū)ο笤O(shè)計(jì)模式中的多態(tài)應(yīng)用多態(tài)是面向?qū)ο笤O(shè)計(jì)模式中的一個(gè)核心概念,它在許多設(shè)計(jì)模式中都有應(yīng)用,如策略模式、工廠模式等。3.4.1原理在策略模式中,多態(tài)允許我們定義一系列算法,并將它們封裝在對象中,以便在運(yùn)行時(shí)選擇和使用。在工廠模式中,多態(tài)允許我們定義一個(gè)接口,用于創(chuàng)建一系列相關(guān)或相互依賴的對象,而無需指定它們具

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

最新文檔

評論

0/150

提交評論