目錄
多態的基本概念
如何實現多態
在C++中,派生類對象可以被當作基類對象使用
編程示例
關鍵概念總結
抽象類
一、抽象類的定義
基本語法
二、抽象類的核心特性
1. 不能直接實例化
2.?派生類必須實現所有純虛函數才能成為具體類
3.?可以包含普通成員函數和數據成員
編程示例
關鍵點說明
接口
接口的基本概念
多態的基本概念
想象一下,你有一個遙控器(這就像是一個基類的指針),這個遙控器可以控制不同的電子設備(這些設備就像是派生類)。無論是電視、音響還是燈光,遙控器上的“開/關”按鈕(這個按鈕就像是一個虛函數)都能控制它們,但具體的操作(打開電視、播放音樂、開燈)則取決于你指向的設備。
如何實現多態
1. 使用虛函數(Virtual Function):
我們在基類中定義一個虛函數,這個函數可以在任何派生類中被“重寫”或者說“定制”。使用關鍵字 virtual 來聲明。
2. 創建派生類并重寫虛函數:
在派生類中,我們提供該虛函數的具體實現。這就像是告訴遙控器,“當你控制我的這個設備時,這個按鈕應該這樣工作”。
3. 通過基類的引用或指針調用虛函數:
當我們使用基類類型的指針或引用來調用虛函數時,實際調用的是對象的實際類型(派生類)中的函數版本。
當基類包含至少一個虛函數(通常是純虛函數),派生類重寫該函數后,在main函數中用基類指針指向派生類對象,并通過該指針調用虛函數時,實際調用的是派生類的實現,這種現象稱為多態。
在C++中,派生類對象可以被當作基類對象使用
-
派生類對象可以直接賦值給基類指針/引用
-
但反過來不行(基類對象不能當作派生類對象)
編程示例
#include <iostream>
using namespace std;// 基類——遙控器(抽象概念)
class RemoteCon
{
public:// 虛函數:聲明遙控器的"開啟"功能,允許子類重寫virtual void open() = 0; // 純虛函數(=0表示沒有默認實現)// 這樣RemoteCon就成為抽象類,不能直接實例化
};// 派生類——電視遙控器,繼承于基類遙控器
class TVRemoteCon : public RemoteCon
{
public:// 重寫(override)基類的open函數void open() override{cout << "電視遙控器開啟鍵被按下" << endl;}
};// 派生類——燈光遙控器,繼承于基類遙控器
class LightRemoteCon : public RemoteCon
{
public:void open() override{cout << "燈光遙控器開啟鍵被按下" << endl;}
};// 派生類——空調遙控器,繼承于基類遙控器
class AirConditionerRemoteCon : public RemoteCon
{
public:void open() override{cout << "空調遙控器開啟鍵被按下" << endl;}
};int main()
{// 第一部分:通過指針實現多態// 創建一個指向電視遙控器的基類指針RemoteCon* remoteCon = new TVRemoteCon(); remoteCon->open(); // 調用TVRemoteCon的open()// 創建一個指向燈光遙控器的基類指針RemoteCon* remoteCon2 = new LightRemoteCon();remoteCon2->open(); // 調用LightRemoteCon的open()// 第二部分:通過引用實現多態AirConditionerRemoteCon kongTiao; // 創建空調遙控器對象RemoteCon& remoteCon3 = kongTiao; // 創建基類引用綁定到派生類對象remoteCon3.open(); // 調用AirConditionerRemoteCon的open()// 釋放動態分配的內存delete remoteCon;delete remoteCon2;return 0;
}
代碼解釋:
RemoteCon *remoteCon = new TVRemoteCon; // 創建一個指向電視的遙控器指針
remoteCon->open();
盡管?remoteCon
?是?RemoteCon*
?類型的指針,但它實際指向的是?TVRemoteCon
?對象。在運行時,C++ 的多態機制會依據對象的實際類型來調用相應的?open
?函數實現,所以這里調用的是?TVRemoteCon
?類中的?open
?函數。
關鍵概念總結
-
虛函數(virtual):允許函數在派生類中被重寫
-
override關鍵字:明確表示重寫基類虛函數
-
多態兩種實現:
-
基類指針指向派生類對象
-
基類引用綁定派生類對象
-
-
運行時綁定:具體調用哪個函數在運行時決定
抽象類
一、抽象類的定義
抽象類是指包含至少一個純虛函數的類,它不能被實例化,只能作為其他類的基類。
基本語法
class 抽象類名 {
public:virtual 返回類型 函數名(參數列表) = 0; // 純虛函數// 其他成員...
};
二、抽象類的核心特性
1. 不能直接實例化
class Shape {
public:virtual double area() = 0;
};// Shape s; // 錯誤!不能創建抽象類對象
2.?派生類必須實現所有純虛函數才能成為具體類
class Circle : public Shape {
public:double area() override { return 3.14*r*r; } // 必須實現
};
3.?可以包含普通成員函數和數據成員
class Animal {
public:virtual void speak() = 0;void eat() { cout << "Eating..." << endl; } // 普通成員函數
protected:int age; // 數據成員
};
編程示例
#include <iostream>using namespace std;// 這是一個抽象類,包含3個純虛函數
// 因為有純虛函數,所有這個類不能被實例化
class Teacher {
public:virtual void course() = 0; // 聲明課程內容的純虛函數virtual void startClass() = 0; // 開始上課的純虛函數virtual void endClass() = 0; // 結束課程的純虛函數
};// 具體派生類 EnglishTeacher
class EnglishTeacher : public Teacher {
public:void course() override {cout << "這節課是英語課" << endl;}void startClass() override {cout << "開始上英語課" << endl;}void endClass() override {cout << "英語課結束" << endl;}
};// 具體派生類 ProTeacher
class ProTeacher : public Teacher {
public:void course() override {cout << "這節課是C++" << endl;}void startClass() override {cout << "開始上C++" << endl;}void endClass() override {cout << "C++結束" << endl;}
};int main() {// 直接使用具體類EnglishTeacher t;t.course(); // 輸出: 這節課是英語課t.startClass(); // 輸出: 開始上英語課t.endClass(); // 輸出: 英語課結束// 多態用法Teacher* t2 = new ProTeacher;t2->course(); // 輸出: 這節課是C++t2->startClass(); // 輸出: 開始上C++t2->endClass(); // 輸出: C++結束delete t2; // 記得釋放內存return 0;
}
關鍵點說明
-
多態的實現:
-
通過基類指針
Teacher*
指向派生類對象ProTeacher
-
調用虛函數時,實際執行的是派生類的實現
-
-
override關鍵字:
-
確保函數確實重寫了基類的虛函數
-
如果簽名不匹配,編譯器會報錯
-
-
抽象類的作用:
-
強制派生類實現特定接口
-
統一了不同種類教師的調用方式
-
-
內存管理:
-
示例中
new ProTeacher
需要手動delete
-
接口
在C++中,接口是一種特殊的抽象類,它只包含純虛函數而不包含任何數據成員或具體實現。接口用于定義行為規范,讓不同的類可以遵循相同的接口標準。
接口的基本概念
在 C++ 中,雖然沒有像其他編程語言(比如 Java 中的接口Interface)一樣直接定義接口的關鍵字,但可以通過抽象類和純虛函數的方式來實現接口的概念。
接口通常用于定義類應該實現的方法,但不提供具體實現。這樣的實現方式允許多個類共享相同的接口,同時讓每個類根據需要去實現這些接口。
一個類作為接口可以通過以下步驟來實現:
1. 定義抽象類:創建一個包含純虛函數的抽象類,這些函數構成了接口的一部分。這些函數在抽象類中只有聲明而沒有具體的實現。
2. 派生類實現接口:派生類繼承抽象類,并實現其中的純虛函數,以具體實現接口定義的方法。
#include <iostream>using namespace std;class Person // 接口
{
public:virtual void eat() = 0; // 吃virtual void drink() = 0; // 喝virtual void haveFun() = 0; // 玩樂
};class Woman : public Person
{
public:void eat() override{cout << "麻辣雞腿堡" << endl;}void drink() override{cout << "珍珠奶茶" << endl;}void haveFun() override{cout << "劇本殺" << endl;}
};class Man : public Person
{
public:void eat() override{cout << "板燒雞腿堡" << endl;}void drink() override{cout << "可樂" << endl;}void haveFun() override{cout << "打桌球" << endl;}
};int main()
{Woman w;w.eat();w.drink();w.haveFun();Man m;m.eat();m.drink();m.haveFun();return 0;
}
Person
?類是一個抽象基類,它包含了三個純虛函數(eat()
,?drink()
,?haveFun()
),這實際上起到了接口的作用。
Woman
?和?Man
?類繼承自?Person
?并實現了所有這些純虛函數。
所以可以說這是一個接口的實現,但更準確的說法是:
-
這是一個使用 C++ 純虛函數實現的接口設計模式
-
Person
?類扮演了接口的角色 -
Woman
?和?Man
?是具體實現這個接口的類
在 C++ 中,這種設計常被稱為"接口類"或"抽象基類",它強制派生類必須實現這些方法,這正是接口的核心特性。
?