網(wǎng)站及網(wǎng)頁設(shè)計費用市場營銷策劃公司排名
1.1QT介紹
1.1.1 QT簡介
Qt 是一個跨平臺的應(yīng)用程序和用戶界面框架,用于開發(fā)圖形用戶界面(GUI)應(yīng)用程序以及命令行工具。它最初由挪威的 Trolltech (奇趣科技)公司開發(fā),現(xiàn)在由 Qt Company 維護(hù),2020年12月8日發(fā)布QT6。Qt 使用 C++ 語言編寫,支持多種編程語言通過綁定進(jìn)行使用。
1.1.2?QT Creator 常用的快捷鍵使用基本介紹


2.1 命名空間
2.1.1命名空間作用
創(chuàng)建自己的命名空間是 C++ 中組織代碼的一種好方法,特別是在開發(fā)大型項目或庫時。命名空間可以幫助你避免名稱沖突,并且清晰地組織代碼。
std 是 C++ 標(biāo)準(zhǔn)庫的命名空間。它是一個定義在 C++ 標(biāo)準(zhǔn)庫中的所有類、函數(shù)和變量的命名空間。
在 C++ 中,如果你想使用標(biāo)準(zhǔn)庫中的任何類、函數(shù)或?qū)ο?#xff0c;你通常有兩種選擇:
1. 使用 std:: 前綴:這是最常見的方式,它明確指定了你正在使用的是位于 std 命名空間中的元
素。
std::cout << "Hello, world!" << std::endl;
2. 使用 using namespace std; :這允許你在不顯式指定 std:: 的情況下使用 std 命名空間中的
所有元素。
using namespace std;
cout << "Hello, world!" << endl;
std包含的內(nèi)容
std 命名空間包含了許多類、函數(shù)和對象,例如:
輸入輸出庫(如 std::cout , std::cin , std::endl )
容器類(如 std::vector , std::map , std::set )
字符串類( std::string )
異常類( std::exception 和相關(guān)子類)
算法(如 std::sort , std::find )
實用工具(如 std::pair , std::tuple )
其他許多功能
使用建議
對于小型代碼或示例代碼,使用 using namespace std; 通常是安全的。
對于大型項目或庫,建議顯式地使用 std:: 前綴,以避免潛在的名稱沖突,并提高代碼的可讀性
和可維護(hù)性。
std 命名空間是 C++ 編程的基礎(chǔ)部分,理解和正確使用它對于編寫健壯和高效的 C++ 代碼至關(guān)重要。
2.1.2自定義命名空間
定義命名空間
假設(shè)我們要創(chuàng)建一個命名空間來包含與圓形相關(guān)的功能。我們可以命名這個命名空間為 cir :
在這個頭文件中,我們定義了一個名為 cir 的命名空間,其中包含了計算圓的面積和周長的函數(shù),以及圓周率常量 PI 。
使用命名空間
在另一個文件中,我們可以使用這個命名空間中定義的函數(shù)和常量:
在 main.cpp 中,我們首先包含了定義 Cir 命名空間的頭文件。然后,我們可以使用 Cir:: 前綴來訪 問該命名空間中的函數(shù)和常量。
通過使用自定義命名空間,你可以有效地組織你的代碼,并減少不同庫之間的名稱沖突。這在大型項目和團(tuán)隊協(xié)作中尤其重要。
輸出結(jié)果
2.2 從C語言快速入門
2.2.1 輸入輸出
C++ 中的輸入和輸出(I/O)主要是通過標(biāo)準(zhǔn)庫中的輸入輸出流來實現(xiàn)的。最常用的是 iostream 庫,它提供了用于輸入和輸出的基本流類,包括 cin 、 cout 、 cerr 和 clog 。
標(biāo)準(zhǔn)輸出流 ( cout )
cout 代表標(biāo)準(zhǔn)輸出流,通常用于向屏幕輸出數(shù)據(jù)。
使用操作符 << (插入操作符)向 cout 發(fā)送數(shù)據(jù)。
例如, std::cout << "Hello, world!" << std::endl; 會在屏幕上打印 "Hello, world!" 并換行。
標(biāo)準(zhǔn)輸入流 ( cin )
cin 代表標(biāo)準(zhǔn)輸入流,用于從鍵盤接收數(shù)據(jù)。
使用操作符 >> (提取操作符)從 cin 提取數(shù)據(jù)。
例如, int x; std::cin >> x; 會從用戶那里讀取一個整數(shù)并存儲在變量 x 中。
標(biāo)準(zhǔn)錯誤流 ( cerr ) 和標(biāo)準(zhǔn)日志流 ( clog )
cerr 用于輸出錯誤消息。與 cout 不同, cerr 不是緩沖的,這意味著它會立即輸出。
clog 類似于 cerr ,但它是緩沖的。它通常用于記錄錯誤和日志信息。
2.2.2 基本變量類型
C++ 基本數(shù)據(jù)類型整理成表格。以下是一個表格,展示了不同的基本數(shù)據(jù)類型及其一般用途和大小范圍:
和C語言類似。
2.2.3?內(nèi)聯(lián)函數(shù)
內(nèi)聯(lián)函數(shù)(Inline Function)是C++中一種特殊的函數(shù),其定義直接在每個調(diào)用點展開。這意味著編譯器會嘗試將函數(shù)調(diào)用替換為函數(shù)本身的代碼,這樣可以減少函數(shù)調(diào)用的開銷,尤其是在小型函數(shù)中。
特點
1. 減少函數(shù)調(diào)用開銷:內(nèi)聯(lián)函數(shù)通常用于優(yōu)化小型、頻繁調(diào)用的函數(shù),因為它避免了函數(shù)調(diào)用的常規(guī)開銷(如參數(shù)傳遞、棧操作等)。
2. 編譯器決策:即使函數(shù)被聲明為內(nèi)聯(lián),編譯器也可能決定不進(jìn)行內(nèi)聯(lián),特別是對于復(fù)雜或遞歸函 數(shù)。
3. 適用于小型函數(shù):通常只有簡單的、執(zhí)行時間短的函數(shù)適合做內(nèi)聯(lián)。
4. 定義在每個使用點:內(nèi)聯(lián)函數(shù)的定義(而非僅僅是聲明)必須對每個使用它的文件都可見,通常意味著將內(nèi)聯(lián)函數(shù)定義在頭文件中。
使用方法
通過在函數(shù)聲明前添加關(guān)鍵字 inline 來指示編譯器該函數(shù)適合內(nèi)聯(lián):
inline int max(int x, int y)
{
????????return x > y ? x : y;
}
示例
#include <iostream>
inline int add(int a, int b)
{
????????return a + b;
}
int main()
{
????????int result = add(5, 3); // 編譯器可能會將此替換為:int result = 5 + 3;
????????std::cout << "Result: " << result << std::endl;
????????return 0;
}
在這個示例中,函數(shù) add 被定義為內(nèi)聯(lián)函數(shù)。當(dāng)它被調(diào)用時,編譯器可能會將函數(shù)調(diào)用替換為函數(shù)體內(nèi)的代碼。
注意事項
過度使用的風(fēng)險:不應(yīng)濫用內(nèi)聯(lián)函數(shù),因為這可能會增加最終程序的大小(代碼膨脹)。對于大型
函數(shù)或遞歸函數(shù),內(nèi)聯(lián)可能導(dǎo)致性能下降。
編譯器的決定:最終是否將函數(shù)內(nèi)聯(lián)是由編譯器決定的,即使函數(shù)被標(biāo)記為 inline 。
適用場景:最適合內(nèi)聯(lián)的是小型函數(shù)和在性能要求高的代碼中頻繁調(diào)用的函數(shù)。
內(nèi)聯(lián)函數(shù)是一種用于優(yōu)化程序性能的工具,但需要合理使用,以確保代碼的可維護(hù)性和性能的平衡。
2.2.4?Lambda 表達(dá)式
Lambda 表達(dá)式是 C++11 引入的一種匿名函數(shù)的方式,它允許你在需要函數(shù)的地方內(nèi)聯(lián)地定義函數(shù),而無需單獨命名函數(shù)
Lambda 表達(dá)式的基本語法如下:
[capture clause](parameters) -> return_type
{
????????// 函數(shù)體
????????// 可以使用捕獲列表中的變量
????????return expression; // 可選的返回語句
}
Lambda 表達(dá)式由以下部分組成:
捕獲列表(Capture clause):用于捕獲外部變量,在 Lambda 表達(dá)式中可以訪問這些變量。捕
獲列表可以為空,也可以包含變量列表 [var1, var2, ...] 。
參數(shù)列表(Parameters):與普通函數(shù)的參數(shù)列表類似,可以為空或包含參數(shù)列表 (param1,
param2, ...) 。
返回類型(Return type):Lambda 表達(dá)式可以自動推斷返回類型auto,也可以顯式指定返回類
型 -> return_type 。如果函數(shù)體只有一條返回語句,可以省略返回類型。
函數(shù)體(Body):Lambda 表達(dá)式的函數(shù)體,包含需要執(zhí)行的代碼。
Lambda 表達(dá)式最簡單的案例是在需要一個小型函數(shù)或臨時函數(shù)時直接使用它。以下是一個非常簡單的例子,其中使用 Lambda 表達(dá)式來定義一個加法操作,并立即使用它來計算兩個數(shù)的和。
#include <iostream>
int main()
{
????????// 定義一個簡單的 Lambda 表達(dá)式進(jìn)行加法
????????auto add = [ ](int a, int b)
????????{
????????????????return a + b;
????????};
????????// 使用 Lambda 表達(dá)式計算兩個數(shù)的和
????????int sum = add(10, 20);
????????std::cout << "Sum is: " << sum << std::endl;
????????return 0;
}
在這個例子中:
我們定義了一個名為 add 的 Lambda 表達(dá)式,它接受兩個整數(shù)參數(shù),并返回它們的和。然后,我們使用這個 Lambda 表達(dá)式來計算兩個數(shù)字(10 和 20)的和,并將結(jié)果存儲在變量 sum中。最后,我們打印出這個和。
這個例子展示了 Lambda 表達(dá)式的基本用法:作為一種簡潔而快速的方式來定義小型函數(shù)。
我們可以寫一個例子,其中使用一個函數(shù)來找出兩個數(shù)中的較大數(shù),這個函數(shù)將接受一個 lambda 函數(shù)作為回調(diào)來比較這兩個數(shù)。Lambda 函數(shù)將直接在函數(shù)調(diào)用時定義,完全是匿名的。
先回憶以下回調(diào)函數(shù)
#include <iostream>
bool myCompare(int a, int b)
{
????????return a > b;
}
int getMax(?int a, int b, bool?(*compare)(int, int) )
{
????????if (compare(a, b))
???????? {
????????????????return a;
????????} else
????????{
????????????????return b;
????????}
}
int main()
{
????????int x = 10;
????????int y = 20;
????????// 回調(diào)函數(shù)
????????int max = getMax(x, y, myCompare);
????????std::cout << "The larger number is: " << max << std::endl;
????????return 0;
}
示例:使用匿名 Lambda 函數(shù)來返回兩個數(shù)中的較大數(shù)
#include <iostream>
// 函數(shù),接受兩個整數(shù)和一個比較的 lambda 函數(shù)
int getMax(int a, int b, bool(*compare)(int, int))
{
????????if (compare(a, b))
????????{
????????????????return a;
????????} else
???????? {
????????????????return b;
????????}
}
int main()
{
????????int x = 10;
????????int y = 20;
????????// 直接在函數(shù)調(diào)用中定義匿名 lambda 函數(shù)
????????int max = getMax(x, y, [ ](int a, int b) -> bool
????????{
????????????????return a > b;
????????});
????????std::cout << "The larger number is: " << max << std::endl;
????????return 0;
}
在這個例子中:
getMax 函數(shù)接受兩個整數(shù) a 和 b ,以及一個比較函數(shù) compare 。這個比較函數(shù)是一個指向函數(shù) 的指針,它接受兩個整數(shù)并返回一個布爾值。在 main 函數(shù)中,我們調(diào)用 getMax ,并直接在調(diào)用點定義了一個匿名的 lambda 函數(shù)。這個lambda 函數(shù)接受兩個整數(shù)并返回一個表示第一個整數(shù)是否大于第二個整數(shù)的布爾值。這個 lambda 函數(shù)在 getMax 中被用作比較兩個數(shù)的邏輯。根據(jù) lambda 函數(shù)的返回值, getMax返回較大的數(shù)。
這個例子展示了如何直接在函數(shù)調(diào)用中使用匿名 lambda 函數(shù),使代碼更加簡潔和直接。這種方法在需要臨時函數(shù)邏輯的場合非常有用,尤其是在比較、條件檢查或小型回調(diào)中。
在 Lambda 表達(dá)式中,參數(shù)捕獲是指 Lambda 表達(dá)式從其定義的上下文中捕獲變量的能力。這使得Lambda 可以使用并操作在其外部定義的變量。捕獲可以按值(拷貝)或按引用進(jìn)行。
讓我們通過一個簡單的示例來展示帶參數(shù)捕獲的 Lambda 表達(dá)式。
輸出
在這個例子中:
第一個 Lambda 表達(dá)式 sum 按值捕獲了 x 和 y (即它們的副本)。這意味著 sum 內(nèi)的 x 和 y
是在 Lambda 定義時的值的拷貝。
第二個 Lambda 表達(dá)式 mul?使用 [=] 捕獲列表,這表示它按值捕獲所有外部變量。
第三個 Lambda 表達(dá)式 modify_mul?使用 [&] 捕獲列表,這表示它按引用捕獲所有外部變量。因此,它可以修改 x 和 y 的原始值。
這個示例展示了如何使用不同類型的捕獲列表(按值和按引用)來控制 Lambda 表達(dá)式對外部變量的訪問和修改。按值捕獲是安全的,但不允許修改原始變量,而按引用捕獲允許修改原始變量,但需要注意引用的有效性和生命周期問題。
以下是一個表格,概述了 Lambda 函數(shù)和內(nèi)聯(lián)函數(shù)在 C++ 中的相似之處和區(qū)別:

請注意,雖然 Lambda 函數(shù)和內(nèi)聯(lián)函數(shù)在某些方面有相似之處,如它們都可以被編譯器優(yōu)化以減少調(diào)用開銷,但它們在設(shè)計和用途上有明顯的不同。Lambda 函數(shù)的核心優(yōu)勢在于它們的匿名性和對外部變量的捕獲能力,而內(nèi)聯(lián)函數(shù)則主要關(guān)注于提高小型函數(shù)的性能。
2.3類
2.3.1 類的初探
C++ 中的類(class)是一種編程結(jié)構(gòu),用于創(chuàng)建對象。這些對象可以擁有屬性(即數(shù)據(jù)成員)和行為(即成員函數(shù)或方法)。類的概念是面向?qū)ο缶幊痰暮诵闹?#xff0c;其主要目的是將數(shù)據(jù)和與數(shù)據(jù)相關(guān)的操作封裝在一起。例如,如果你有一個“汽車”類,它可能包含顏色、品牌、型號等屬性(數(shù)據(jù)成員),以及啟動、停止、加速等行為(成員函數(shù))。每當(dāng)你基于這個類創(chuàng)建一個對象時,你就有了一個具體的汽車,具有這些屬性和行為。
C++ 類的基本結(jié)構(gòu)通常包含:
1. 數(shù)據(jù)成員(Attributes):定義類的屬性。這些是類內(nèi)部的變量,用于存儲對象的狀態(tài)。
2. 成員函數(shù)(Methods):定義類的行為。這些是可以操作對象的數(shù)據(jù)成員的函數(shù)。
3. 構(gòu)造函數(shù)和析構(gòu)函數(shù):特殊的成員函數(shù)。構(gòu)造函數(shù)在創(chuàng)建對象時自動調(diào)用,用于初始化對象。析構(gòu)函數(shù)在對象銷毀時調(diào)用,用于執(zhí)行清理操作。
4. 訪問修飾符:如 public , private , protected ,用于控制對類成員的訪問權(quán)限。例如, public成員可以在類的外部訪問,而 private 成員只能在類內(nèi)部訪問。
5. 繼承:允許一個類繼承另一個類的特性。這是代碼重用和多態(tài)性的關(guān)鍵。
通過這些特性,C++ 類提供了一種強(qiáng)大的方式來組織和處理數(shù)據(jù),使得代碼更加模塊化、易于理解和維護(hù)。
2.3.2 結(jié)構(gòu)體引入類
2.3.2.1 回憶結(jié)構(gòu)體
如果用C語言實現(xiàn)上面描述的汽車類,我們實現(xiàn)如下代碼
輸出
2.3.2.2 新建C++工程來使用結(jié)構(gòu)體
在C++中,字符串用string來表示,發(fā)現(xiàn)有個string賦值給char 的警告,所以修改所有char *為 string類型
main . cpp : 33 : 17 : warning : ISO C ++ 11 does not allow conversion from string literalto 'char *'
修改后,發(fā)現(xiàn)printf的%s控制位,不能用于string的輸出,所有有string構(gòu)建了即將要輸出的字符串
C++中,通過std::tostring()函數(shù),將整型數(shù)轉(zhuǎn)化成字符串
在printCarInfo中使用cout輸出汽車信息
發(fā)現(xiàn)在C++工程中,使用malloc在堆申請結(jié)構(gòu)體空間有問題,所以直接在此引入類的概念,把struct改成class
引入新問題,class的成員數(shù)據(jù)和成員函數(shù)在不指定權(quán)限的情況下,默認(rèn)private權(quán)限,類的對象無法進(jìn)行直接訪問
main.cpp:33:9: error: 'color' is a private member of 'Car'
main.cpp:5:11: note: implicitly declared private here
添加public屬性
把main函數(shù)中的原本結(jié)構(gòu)體變量改成了類的實例化,如果變量類型是指針,把原來的malloc改成
new一個對象
最后解決了所有問題
2.3.2.3 真正的成員函數(shù)
上一節(jié)的案例中, void (*printCarInfo)(string color,string brand,string type, int year); 到底是變量函數(shù)還是成員函數(shù)呢?
答:是一個指針變量,是保存某個函數(shù)地址的變量,所以它不是成員函數(shù),是成員數(shù)據(jù)
真正的成員函數(shù)遵守封裝特性,在函數(shù)體內(nèi)部訪問成員數(shù)據(jù)的時候,不需要參數(shù)傳遞
在 C++ 中,雙冒號 :: 稱為 "作用域解析運(yùn)算符"(Scope Resolution Operator)。它用于指定一
個成員(如函數(shù)或變量)屬于特定的類或命名空間。例如,在類的外部定義成員函數(shù)時, :: 用于
指明該函數(shù)屬于哪個類。
2.3.4 QT中經(jīng)常出現(xiàn)的用法
在 C++中,一個類包含另一個類的對象稱為組合(Composition)。這是一種常見的設(shè)計模式,用
于表示一個類是由另一個類的對象組成的。這種關(guān)系通常表示一種"擁有"("has-a")的關(guān)系。
普通變量訪問成員變量或者成員函數(shù),使用 “ . ” 運(yùn)算符
指針變量訪問成員變量或者成員函數(shù),使用“ -> ”運(yùn)算符,像C語言的結(jié)構(gòu)體用法
輸出
2.4 權(quán)限初識
2.4.1 基本介紹
C++中的訪問權(quán)限主要分為三種: public 、 private 和 protected 。這些權(quán)限決定了類成員(包括數(shù)據(jù)成員和成員函數(shù))的可訪問性。以下是一個總結(jié)表格,說明了在不同情況下這些權(quán)限如何應(yīng)用:
使用權(quán)限(如 public 、 private 和 protected )在C++中是一種關(guān)鍵的封裝手段,它們旨在控制對類成員的訪問。下面是一個表格,總結(jié)了使用權(quán)限的主要好處和潛在缺點:
2.4.2 目前能概況的結(jié)論
public 權(quán)限相當(dāng)于我們學(xué)習(xí)C語言結(jié)構(gòu)體一樣,不考慮訪問權(quán)限的存在,但是要注意,類中不寫權(quán)
限,默認(rèn)是私有權(quán)限
protected 留到繼承講解的時候再提
private 私有權(quán)限,通過一下案例向各位表達(dá)一下作用的意思,但需要未來實戰(zhàn)中慢慢體會。
這個例子將闡述在類設(shè)計中使用 private 成員的必要性。我們將創(chuàng)建一個簡單的 BankAccount 類,展示如何使用 private 來保護(hù)賬戶的余額,確保它只能通過指定的方法進(jìn)行修改。
所以,我們可以腦部一個場景:
銀行的賬戶是一個模板,是一個類,有存款人信息和賬戶額度,而具體的存款人視為一個對象,一個對象不能私自修改賬戶額度,需要通過一個操作流程,比如去ATM或者柜臺進(jìn)行操作才能修改到賬戶額度,所以,存款人信息和賬戶額度設(shè)計成私有權(quán)限,通過公有的操作流程,也就是公有函數(shù)去操作私有變量。
基于這個場景,我們編程實現(xiàn)代碼
輸出
在這個示例中, balance 是一個 private 成員變量,它不能被類的外部直接訪問。這保證了賬戶余額只能通過類提供的方法(如 putinMoney?, getfromMoney, 和 getBalance )來修改和查詢,從而防止了不合適的修改,比如直接設(shè)置余額為負(fù)數(shù)或任意值。這樣的設(shè)計保證了類的封裝性和數(shù)據(jù)的完整性。
2.4.3 提問和回答
問:為什么新手學(xué)習(xí)C++感受不到訪問權(quán)限的必要性呢?
答:新手學(xué)習(xí)C++時可能不會立即感受到訪問權(quán)限(如 public 、 private 、 protected )的必要性,主要有以下幾個原因:
1. 簡單的例子和練習(xí):初學(xué)者通常從簡單的例子和練習(xí)開始,這些例子可能不需要復(fù)雜的封裝或繼承結(jié)構(gòu)。在這種情況下,訪問權(quán)限的作用可能不太明顯。
2. 封裝的概念需要時間去理解:封裝是面向?qū)ο缶幊讨械囊粋€核心概念,但對于初學(xué)者來說,理解封裝的價值需要一定的時間和實踐。在初期,更多的關(guān)注點可能放在基本語法和程序結(jié)構(gòu)上。
3. 缺乏大型項目經(jīng)驗:在小型項目或單文件程序中,訪問權(quán)限的重要性可能不如在大型、多人協(xié)作的項目中那么顯著。在復(fù)雜的軟件開發(fā)中,適當(dāng)?shù)脑L問控制對于代碼的維護(hù)性和可讀性至關(guān)重要。
4. 直接操作感覺更簡單:對于初學(xué)者來說,直接訪問和修改類的所有成員可能看起來更簡單直接。他們可能還沒有遇到由于不恰當(dāng)訪問控制導(dǎo)致的維護(hù)和調(diào)試問題。
5. 抽象和設(shè)計模式的理解:理解何時以及如何使用訪問權(quán)限通常涉及到對軟件設(shè)計模式和抽象的深入理解。這些通常是隨著經(jīng)驗積累和更深入的學(xué)習(xí)而逐漸掌握的。
隨著經(jīng)驗的增長,學(xué)習(xí)者開始處理更復(fù)雜的項目,他們將開始意識到恰當(dāng)?shù)脑L問控制的重要性,特別是在保持代碼的可維護(hù)性、可讀性以及在團(tuán)隊環(huán)境中的協(xié)作方面。因此,對于教育者和學(xué)習(xí)者來說,強(qiáng)調(diào)并實踐這些概念是很重要的,以便在編程技能成熟時能夠有效地運(yùn)用它們。
2.5 引用
引用變量是一個別名,也就是說,它是某個已存在變量的另一個名字。
一旦把引用初始化為某個變量,就可以使用該引用名稱或變量名稱來指向變量。
思維發(fā)散:
在C語言中,一個數(shù)據(jù)對應(yīng)一個內(nèi)存,通過由一個變量名來訪問這個內(nèi)存空間的數(shù)據(jù),叫做直接訪問,相對直接訪問,有個間接訪問的說法,叫做指針。
而引用相當(dāng)于又給這個內(nèi)存中的數(shù)據(jù)提供了一個新的變量名,
這個變量名功能比傳統(tǒng)變量名更特殊,是直達(dá)地址的,后續(xù)代碼驗證!
2.5.1 和指針的區(qū)別
引用很容易與指針混淆,它們之間有三個主要的不同:
1.不存在空引用。引用必須連接到一塊合法的內(nèi)存。
2.一旦引用被初始化為一個對象,就不能被指向到另一個對象。指針可以在任何時候指向到另一個對象。
3.引用必須在創(chuàng)建時被初始化。指針可以在任何時間被初始化。
官方?jīng)]有明確說明,但是引用確實不是傳統(tǒng)意義上的獨立變量,它不能“變”嘛
試想變量名稱是變量附屬在內(nèi)存位置中的標(biāo)簽,可以把引用當(dāng)成是變量附屬在內(nèi)存位置中的第二
個標(biāo)簽。因此,可以通過原始變量名稱或引用來訪問變量的內(nèi)容。例如:
int i = 17 ; int* p = & i ; * p = 20 ;
我們可以為 i 聲明引用變量,如下所示:
int& r = i;
double& s = d;
在這些聲明中,& 讀作引用。
因此,第一個聲明可以讀作 "r 是一個初始化為 i 的整型引用",第二個聲明可以讀作 "s 是一個初始化為 d 的 double 型引用"。
下面的實例使用了 int 和 double 引用:
輸出
2.5.2 把引用作為參數(shù)
我們已經(jīng)討論了如何使用指針來實現(xiàn)引用調(diào)用函數(shù)。下面的實例使用了引用來實現(xiàn)引用調(diào)用函數(shù)。

輸出
2.5.3 把引用作為返回值
通過使用引用來替代指針,會使 C++ 程序更容易閱讀和維護(hù)。C++ 函數(shù)可以返回一個引用,方式與返回一個指針類似。
當(dāng)函數(shù)返回一個引用時,則返回一個指向返回值的隱式指針。
這樣,函數(shù)就可以放在賦值語句的左邊。
例如,請看下面這個簡單的程序:
輸出
2.6 重載
2.6.1 函數(shù)重載
在同一個作用域內(nèi),可以聲明幾個功能類似的同名函數(shù),這些同名函數(shù)的形式參數(shù)(指參數(shù)的個數(shù)、類型或者順序)必須不同。不能僅通過返回類型的不同來重載函數(shù)。
下面的實例中,同名函數(shù) print() 被用于輸出不同的數(shù)據(jù)類型:
輸出
2.7 構(gòu)造函數(shù)
2.7.1 什么是構(gòu)造函數(shù)
類的構(gòu)造函數(shù)是類的一種特殊的成員函數(shù),它會在每次創(chuàng)建類的新對象時執(zhí)行。
構(gòu)造,那構(gòu)造的是什么呢?
構(gòu)造成員變量的初始化值,內(nèi)存空間等
構(gòu)造函數(shù)的名稱與類的名稱是完全相同的,并且不會返回任何類型,也不會返回 void。構(gòu)造函數(shù)可用于為某些成員變量設(shè)置初始值。
2.7.2 帶參數(shù)構(gòu)造函數(shù)
默認(rèn)的構(gòu)造函數(shù)沒有任何參數(shù),但如果需要,構(gòu)造函數(shù)也可以帶有參數(shù)。這樣在創(chuàng)建對象時就會給對象賦初始值
下面的實例有助于更好地理解構(gòu)造函數(shù)的概念:
輸出
2.7.3?使用初始化列表
在C++中,使用初始化列表來初始化類的字段是一種高效的初始化方式,尤其在構(gòu)造函數(shù)中。初始化列表直接在對象的構(gòu)造過程中初始化成員變量,而不是先創(chuàng)建成員變量后再賦值。這對于提高性能尤其重要,特別是在涉及到復(fù)雜對象或引用和常量成員的情況下。
初始化列表緊跟在構(gòu)造函數(shù)參數(shù)列表后面,以冒號( : )開始,后跟一個或多個初始化表達(dá)式,每個表達(dá)式通常用逗號分隔。下面是使用初始化列表初始化字段的例子:
輸出
初始化列表的優(yōu)點包括:
1. 效率:對于非基本類型的對象,使用初始化列表比在構(gòu)造函數(shù)體內(nèi)賦值更高效,因為它避免了先默認(rèn)構(gòu)造然后再賦值的額外開銷。
2. 必要性:對于引用類型和常量類型的成員變量,必須使用初始化列表,因為這些類型的成員變量在構(gòu)造函數(shù)體內(nèi)不能被賦值。
3. 順序:成員變量的初始化順序是按照它們在類中聲明的順序,而不是初始化列表中的順序。
使用初始化列表是C++中推薦的初始化類成員變量的方式,因為它提供了更好的性能和靈活性。
2.7.4?this關(guān)鍵字
在 C++ 中, this 關(guān)鍵字是一個指向調(diào)用對象的指針。它在成員函數(shù)內(nèi)部使用,用于引用調(diào)用該函數(shù)的對象。使用 this 可以明確指出成員函數(shù)正在操作的是哪個對象的數(shù)據(jù)成員。
示例代碼
下面的代碼展示了如何使用 this 關(guān)鍵字:
輸出
在這個例子中, Car 類的構(gòu)造函數(shù)使用 this 指針來區(qū)分成員變量和構(gòu)造函數(shù)參數(shù)。同樣, setYear 成員函數(shù)使用 this 指針來返回調(diào)用該函數(shù)的對象的引用,這允許鏈?zhǔn)秸{(diào)用,如 myCar.setYear(2021).display(); 。在 main 函數(shù)中創(chuàng)建了 Car 類型的對象,并展示了如何使用這 些成員函數(shù)。
2.7.5?new關(guān)鍵字
在C++中, new 關(guān)鍵字用于動態(tài)分配內(nèi)存。它是C++中處理動態(tài)內(nèi)存分配的主要工具之一,允許在程序運(yùn)行時根據(jù)需要分配內(nèi)存。
基本用法
分配單個對象:使用 new 可以在堆上動態(tài)分配一個對象。例如, new int 會分配一個 int 類型的空
間,并返回一個指向該空間的指針。
int* ptr = new int; //C語言中,int *p = (int *)malloc(sizeof(int));
分配對象數(shù)組: new 也可以用來分配一個對象數(shù)組。例如, new int[10] 會分配一個包含10個整數(shù)的數(shù)組。
int* arr = new int [ 10 ]; //C 語言中, int *arr = (int *)malloc(sizeof(int)*10);
初始化:可以在 new 表達(dá)式中使用初始化。對于單個對象,可以使用構(gòu)造函數(shù)的參數(shù):
MyClass * obj = new MyClass ( arg1 , arg2 );
與 delete 配對使用
使用 new 分配的內(nèi)存必須顯式地通過 delete (對于單個對象)或 delete[] (對于數(shù)組)來釋放,以避免內(nèi)存泄露:
釋放單個對象:
delete ptr; // 釋放 ptr 指向的對象
釋放數(shù)組:
delete[] arr; // 釋放 arr 指向的數(shù)組
注意事項
異常安全:如果 new 分配內(nèi)存失敗,它會拋出 std::bad_alloc 異常。
內(nèi)存泄露:忘記釋放使用 new 分配的內(nèi)存會導(dǎo)致內(nèi)存泄露。
匹配使用 delete 和 delete[ ] :為避免未定義行為,使用 new 分配的單個對象應(yīng)該使用
delete 釋放,使用 new[ ] 分配的數(shù)組應(yīng)該使用 delete[ ] 釋放。
示例代碼
class MyClass{public :????????MyClass ()????????{????????????????std::cout << "Object created" << std::endl ;????????}};int main (){????????// 分配單個對象????????MyClass * myObject = new MyClass ();????????// 分配對象數(shù)組????????int* myArray = new int [ 5 ]{ 1 , 2 , 3 , 4 , 5 };????????// 使用對象和數(shù)組 ...????????// 釋放內(nèi)存????????delete myObject ;????????delete [ ] myArray ;????????return 0 ;}
在這個例子中, new 被用來分配一個 MyClass 類型的對象和一個整數(shù)數(shù)組,然后使用 delete 和
delete[] 來釋放內(nèi)存。每個 new 都對應(yīng)一個 delete ,保證了動態(tài)分配的內(nèi)存被適當(dāng)管理。
2.8 析構(gòu)函數(shù)
2.8.1 什么是析構(gòu)函數(shù)
析構(gòu)函數(shù)是C++中的一個特殊的成員函數(shù),它在對象生命周期結(jié)束時被自動調(diào)用,用于執(zhí)行對象銷毀前的清理工作。析構(gòu)函數(shù)特別重要,尤其是在涉及動態(tài)分配的資源(如內(nèi)存、文件句柄、網(wǎng)絡(luò)連接等)的情況下。
基本特性
1. 名稱:析構(gòu)函數(shù)的名稱由波浪號( ~ )后跟類名構(gòu)成,如 ~MyClass() 。
2. 無返回值和參數(shù):析構(gòu)函數(shù)不接受任何參數(shù),也不返回任何值。
3. 自動調(diào)用:當(dāng)對象的生命周期結(jié)束時(例如,一個局部對象的作用域結(jié)束,或者使用 delete 刪除一個動態(tài)分配的對象),析構(gòu)函數(shù)會被自動調(diào)用。
4. 不可重載:每個類只能有一個析構(gòu)函數(shù)。
5. 繼承和多態(tài):如果一個類是多態(tài)基類,其析構(gòu)函數(shù)應(yīng)該是虛的。
示例
假設(shè)我們有一個類 MyClass ,它包含了動態(tài)分配的內(nèi)存或其他資源:
輸出
在這個示例中, MyClass 的構(gòu)造函數(shù)分配了一塊內(nèi)存,而析構(gòu)函數(shù)釋放了這塊內(nèi)存。當(dāng) obj 的生命周期結(jié)束時(即離開了它的作用域), MyClass 的析構(gòu)函數(shù)被自動調(diào)用,負(fù)責(zé)清理資源,防止內(nèi)存泄露。
重要性
析構(gòu)函數(shù)在管理資源方面非常重要。沒有正確實現(xiàn)析構(gòu)函數(shù),可能導(dǎo)致資源泄露或其他問題。在基于RAII(資源獲取即初始化)原則的C++編程實踐中,確保資源在對象析構(gòu)時被適當(dāng)釋放是非常關(guān)鍵的。當(dāng)使用智能指針和其他自動資源管理技術(shù)時,可以減少顯式編寫析構(gòu)函數(shù)的需要,但了解析構(gòu)函數(shù)的工作原理仍然很重要。
以下是關(guān)于 C++ 中析構(gòu)函數(shù)需要了解的十個要點的表格:
2.9 靜態(tài)成員
2.9.1 靜態(tài)成員的定義
靜態(tài)成員在C++類中是一個重要的概念,它包括靜態(tài)成員變量和靜態(tài)成員函數(shù)。靜態(tài)成員的特點和存在的
意義如下:
靜態(tài)成員變量
1. 定義:靜態(tài)成員變量是類的所有對象共享的變量。與普通成員變量相比,無論創(chuàng)建了多少個類的實例,靜態(tài)成員變量只有一份拷貝。
2. 初始化:靜態(tài)成員變量需要在類外進(jìn)行初始化,通常在類的實現(xiàn)文件中。
3. 訪問:靜態(tài)成員變量可以通過類名直接訪問,不需要創(chuàng)建類的對象。也可以通過類的對象訪問。
4. 用途:常用于存儲類級別的信息(例如,計數(shù)類的實例數(shù)量)或全局?jǐn)?shù)據(jù)需要被類的所有實例共 享。
靜態(tài)成員函數(shù)
1. 定義:靜態(tài)成員函數(shù)是可以不依賴于類的實例而被調(diào)用的函數(shù)。它不能訪問類的非靜態(tài)成員變量和非靜態(tài)成員函數(shù)。
2. 訪問:類似于靜態(tài)成員變量,靜態(tài)成員函數(shù)可以通過類名直接調(diào)用,也可以通過類的實例調(diào)用。
3. 用途:常用于實現(xiàn)與具體對象無關(guān)的功能,或訪問靜態(tài)成員變量。
示例代碼
存在的意義
共享數(shù)據(jù):允許對象之間共享數(shù)據(jù),而不需要每個對象都有一份拷貝。
節(jié)省內(nèi)存:對于頻繁使用的類,使用靜態(tài)成員可以節(jié)省內(nèi)存。
獨立于對象的功能:靜態(tài)成員函數(shù)提供了一種在不創(chuàng)建對象的情況下執(zhí)行操作的方法,這對于實現(xiàn)
工具函數(shù)或管理類級別狀態(tài)很有用。
2.9.2 靜態(tài)成員變量的作用
靜態(tài)成員變量在C++中的一個典型應(yīng)用是用于跟蹤類的實例數(shù)量。這個案例體現(xiàn)了靜態(tài)成員變量的特性:
它們在類的所有實例之間共享,因此適合于存儲所有實例共有的信息。
下面是一個示例,展示了如何使用靜態(tài)成員變量來計數(shù)一個類的實例數(shù)量:
?在這個例子中:
Myclass 類有一個靜態(tài)成員變量 staticNumofInstance ,用來跟蹤該類的實例數(shù)量。
每當(dāng)創(chuàng)建 Myclass 的新實例時,構(gòu)造函數(shù)會增加 staticNumofInstance 。
每當(dāng)一個 Myclass 實例被銷毀時,析構(gòu)函數(shù)會減少 staticNumofInstance 。
通過靜態(tài)成員函數(shù) getNunofInstance 可以隨時獲取當(dāng)前的實例數(shù)量。
靜態(tài)成員變量 staticNumofInstance 在類外初始化為0。
這個案例展示了靜態(tài)成員變量如何在類的所有實例之間共享,并為所有實例提供了一個共同的狀態(tài)(在這個例子中是實例的數(shù)量)。這種技術(shù)在需要跟蹤對象數(shù)量或?qū)崿F(xiàn)某種形式的資源管理時特別有用。?
2.10 繼承
2.10.1 繼承基本概念
繼承是面向?qū)ο缶幊?#xff08;OOP)中的一個核心概念,特別是在C++中。它允許一個類(稱為派生類或子類)繼承另一個類(稱為基類或父類)的屬性和方法。繼承的主要目的是實現(xiàn)代碼重用,以及建立一種類型之間的層次關(guān)系。
特點
1. 代碼重用:子類繼承了父類的屬性和方法,減少了代碼的重復(fù)編寫。
2. 擴(kuò)展性:子類可以擴(kuò)展父類的功能,添加新的屬性和方法,或者重寫(覆蓋)現(xiàn)有的方法。
3. 多態(tài)性:通過繼承和虛函數(shù),C++支持多態(tài),允許在運(yùn)行時決定調(diào)用哪個函數(shù)。
基本用法
在C++中,繼承可以是公有(public)、保護(hù)(protected)或私有(private)的,這決定了基類成員在派生類中的訪問權(quán)限。
輸出
在這個例子中, Bickle?類和Roadster類公有地繼承自 Vehicle 類,這意味著所有 Vehicle 類的公有成員在Bickle?類和Roadster類中也是公有的。
2.10.2 權(quán)限對繼承的影響
在C++中,訪問控制符對繼承的影響可以通過下表來清晰地展示。這個表格展示了不同類型的繼承
( public 、 protected 、 private )如何影響基類的不同類型成員( public 、 protected 、
private )在派生類中的訪問級別。
解釋:
public 繼承:基類的 public 成員在派生類中仍然是 public 的, protected 成員仍然是
protected 的?;惖?private 成員在派生類中不可訪問。
protected 繼承:基類的 public 和 protected 成員在派生類中都變成 protected 的。基類
的 private 成員在派生類中不可訪問。
private 繼承:基類的 public 和 protected 成員在派生類中都變成 private 的?;惖?
private 成員在派生類中不可訪問。
這個表格提供了一個快速參考,幫助理解在不同類型的繼承中基類成員的訪問級別是如何變化的。記住,無論繼承類型如何,基類的 private 成員始終不可直接在派生類中訪問。
2.10.3 基類構(gòu)造函數(shù)
在C++中,派生類可以通過其構(gòu)造函數(shù)的初始化列表來調(diào)用基類的構(gòu)造函數(shù)。這是在構(gòu)造派生類對象時初始化基類部分的標(biāo)準(zhǔn)做法。
當(dāng)創(chuàng)建派生類的對象時,基類的構(gòu)造函數(shù)總是在派生類的構(gòu)造函數(shù)之前被調(diào)用。如果沒有明確指定,將調(diào)用基類的默認(rèn)構(gòu)造函數(shù)。如果基類沒有默認(rèn)構(gòu)造函數(shù),或者你需要調(diào)用一個特定的基類構(gòu)造函數(shù),就需要在派生類構(gòu)造函數(shù)的初始化列表中明確指定。
輸出
2.10.4 虛函數(shù)
在C++中, virtual 和 override 關(guān)鍵字用于支持多態(tài),尤其是在涉及類繼承和方法重寫的情況下。正確地理解和使用這兩個關(guān)鍵字對于編寫可維護(hù)和易于理解的面向?qū)ο蟠a至關(guān)重要。
virtual 關(guān)鍵字
1. 使用場景:在基類中聲明虛函數(shù)。
2. 目的:允許派生類重寫該函數(shù),實現(xiàn)多態(tài)。
3. 行為:當(dāng)通過基類的指針或引用調(diào)用一個虛函數(shù)時,調(diào)用的是對象實際類型的函數(shù)版本。
override 關(guān)鍵字
1. 使用場景:在派生類中重寫虛函數(shù)。
2. 目的:明確指示函數(shù)意圖重寫基類的虛函數(shù)。
3. 行為:確保派生類的函數(shù)確實重寫了基類中的一個虛函數(shù)。如果沒有匹配的虛函數(shù),編譯器會報
錯。
輸出:自行車跑起來
注意點
只在派生類中使用 override: override 應(yīng)僅用于派生類中重寫基類的虛函數(shù)。
虛析構(gòu)函數(shù):如果類中有虛函數(shù),通常應(yīng)該將析構(gòu)函數(shù)也聲明為虛的。
默認(rèn)情況下,成員函數(shù)不是虛的:在C++中,成員函數(shù)默認(rèn)不是虛函數(shù)。只有顯式地使用 virtual
關(guān)鍵字才會成為虛函數(shù)。
繼承中的虛函數(shù):一旦在基類中聲明為虛函數(shù),該函數(shù)在所有派生類中自動成為虛函數(shù),無論是否
使用 virtual 關(guān)鍵字。
正確使用 virtual 和 override 關(guān)鍵字有助于清晰地表達(dá)程序員的意圖,并利用編譯器檢查來避免常
見的錯誤,如簽名不匹配導(dǎo)致的非預(yù)期的函數(shù)重寫。
2.10.5 多重繼承
在C++中,多重繼承是一種允許一個類同時繼承多個基類的特性。這意味著派生類可以繼承多個基類的屬性和方法。多重繼承增加了語言的靈活性,但同時也引入了額外的復(fù)雜性,特別是當(dāng)多個基類具有相同的成員時。
基本概念
在多重繼承中,派生類繼承了所有基類的特性。這包括成員變量和成員函數(shù)。如果不同的基類有相同名稱的成員,則必須明確指出所引用的是哪個基類的成員。
示例
假設(shè)有兩個基類 ClassA 和 ClassB ,以及一個同時從這兩個類繼承的派生類 Derived :
class ClassA
{
public:
????????void displayA()
????????{
????????????????std::cout << "Displaying ClassA" << std::endl;
????????}
};
class ClassB
{
public:
????????void displayB()
????????{
????????????????std::cout << "Displaying ClassB" << std::endl;
????????}
};
class Derived : public ClassA, public ClassB
{
public:
????????void display()
????????{
????????????????displayA(); // 調(diào)用 ClassA 的 displayA
????????????????displayB(); // 調(diào)用 ClassB 的 displayB
????????}
};
int main()
{
????????Derived obj;
????????obj.displayA(); // 調(diào)用 ClassA 的 displayA
????????obj.displayB(); // 調(diào)用 ClassB 的 displayB
????????obj.display(); // 調(diào)用 Derived 的 display
????????return 0;
}
在這個示例中, Derived 類同時繼承了 ClassA 和 ClassB 。因此,它可以使用這兩個類中定義的方法。
在這個實例中,如果不同的基類有相同名稱的成員,則必須明確指出所引用的是哪個基類的成員。
注意事項
菱形繼承問題:如果兩個基類繼承自同一個更高層的基類,這可能導(dǎo)致派生類中存在兩份基類的副
本,稱為菱形繼承(或鉆石繼承)問題。這可以通過虛繼承來解決。
復(fù)雜性:多重繼承可能會使類的結(jié)構(gòu)變得復(fù)雜,尤其是當(dāng)繼承層次較深或類中有多個基類時。
設(shè)計考慮:雖然多重繼承提供了很大的靈活性,但過度使用可能導(dǎo)致代碼難以理解和維護(hù)。在一些
情況下,使用組合或接口(純虛類)可能是更好的設(shè)計選擇。
多重繼承是C++的一個強(qiáng)大特性,但應(yīng)謹(jǐn)慎使用。合理地應(yīng)用多重繼承可以使代碼更加靈活和強(qiáng)大,但不當(dāng)?shù)氖褂每赡軐?dǎo)致設(shè)計上的問題和維護(hù)困難。
2.10.6 虛繼承
虛繼承是C++中一種特殊的繼承方式,主要用來解決多重繼承中的菱形繼承問題。在菱形繼承結(jié)構(gòu)中,一個類繼承自兩個具有共同基類的類時,會導(dǎo)致共同基類的成員在派生類中存在兩份拷貝,這不僅會導(dǎo)致資源浪費,還可能引起數(shù)據(jù)不一致的問題。虛繼承通過確保共同基類的單一實例存在于繼承層次中,來解決這一問題。
菱形繼承問題示例
考慮以下的類結(jié)構(gòu):
class Base
{
public:
????????int data;
};
class Derived1 : public Base
{
????????// 繼承自 Base
};
class Derived2 : public Base
{
????????// 繼承自 Base
};
class FinalDerived : public Derived1, public Derived2
{
????????// 繼承自 Derived1 和 Derived2
};
在這個例子中, FinalDerived 類通過 Derived1 和 Derived2 間接地繼承自 Base 類兩次。因此,
它包含了兩份 Base 的成員拷貝。
使用虛繼承解決菱形繼承問題
要解決這個問題,應(yīng)使用虛繼承:
class Base
{
public:
????????int data;
};
class Derived1 : virtual public Base
{
????????// 虛繼承 Base
};
class Derived2 : virtual public Base
{
????????// 虛繼承 Base
};
class FinalDerived : public Derived1, public Derived2
{
????????// 繼承自 Derived1 和 Derived2
};
通過將 Derived1 和 Derived2 對 Base 的繼承聲明為虛繼承( virtual public Base ),
FinalDerived 類中只會有一份 Base 類的成員。無論通過 Derived1 還是 Derived2 的路徑,訪問
的都是同一個 Base 類的成員。
特點和注意事項
初始化虛基類:在使用虛繼承時,虛基類(如上例中的 Base 類)只能由最派生的類(如
FinalDerived )初始化。
內(nèi)存布局:虛繼承可能會改變類的內(nèi)存布局,通常會增加額外的開銷,比如虛基類指針。
設(shè)計考慮:虛繼承應(yīng)謹(jǐn)慎使用,因為它增加了復(fù)雜性。在實際應(yīng)用中,如果可以通過其他設(shè)計(如
組合或接口)避免菱形繼承,那通常是更好的選擇。
虛繼承是C++語言中處理復(fù)雜繼承關(guān)系的一種重要機(jī)制,但它也帶來了一定的復(fù)雜性和性能考慮。正確地使用虛繼承可以幫助你建立清晰、有效的類層次結(jié)構(gòu)。
2.11 多態(tài)
多態(tài)的基本概念(polymorphic)
想象一下,你有一個遙控器(這就像是一個基類的指針),這個遙控器可以控制不同的電子設(shè)備(這些設(shè)備就像是派生類)。無論是電視、音響還是燈光,遙控器上的“開/關(guān)”按鈕(這個按鈕就像是一個虛函數(shù))都能控制它們,但具體的操作(打開電視、播放音樂、開燈)則取決于你指向的設(shè)備。
2.11.1 如何實現(xiàn)多態(tài)
1. 使用虛函數(shù)(Virtual Function):
我們在基類中定義一個虛函數(shù),這個函數(shù)可以在任何派生類中被“重寫”或者說“定制”。
使用關(guān)鍵字 virtual 來聲明。
2. 創(chuàng)建派生類并重寫虛函數(shù):
在派生類中,我們提供該虛函數(shù)的具體實現(xiàn)。這就像是告訴遙控器,“當(dāng)你控制我的這個設(shè)備
時,這個按鈕應(yīng)該這樣工作”。
3. 通過基類的引用或指針調(diào)用虛函數(shù):
當(dāng)我們使用基類類型的指針或引用來調(diào)用虛函數(shù)時,實際調(diào)用的是對象的實際類型(派生類)
中的函數(shù)版本。

在這個例子中,不同的對象( TvRemoteCon 和 TvRemoteCon )以它們自己的方式“開”,盡管調(diào)用的是相同的函數(shù) openUtils 。這就是多態(tài)的魅力——相同的接口,不同的行為。
為什么使用多態(tài)
靈活性:允許我們編寫可以處理不確定類型的對象的代碼。
可擴(kuò)展性:我們可以添加新的派生類而不必修改使用基類引用或指針的代碼。
接口與實現(xiàn)分離:我們可以設(shè)計一個穩(wěn)定的接口,而將具體的實現(xiàn)留給派生類去處理。
2.11.2 抽象類
抽象類的基本概念
想象一下,你有一個“交通工具”的概念。這個概念告訴你所有交通工具都應(yīng)該能做什么,比如移動
(move),但它并不具體說明怎么移動。對于不同的交通工具,比如汽車和自行車,它們的移動方式是不同的。在這個意義上,“交通工具”是一個抽象的概念,因為它本身并不能直接被使用。你需要一個具體的交通工具,比如“汽車”或“自行車”,它們根據(jù)“交通工具”的概念具體實現(xiàn)了移動的功能。
在 C++ 中,抽象類就像是這樣的一個抽象概念。它定義了一組方法(比如移動),但這些方法可能沒有具體的實現(xiàn)。這意味著,抽象類定義了派生類應(yīng)該具有的功能,但不完全實現(xiàn)這些功能。
抽象類的特點
1. 包含至少一個純虛函數(shù):
抽象類至少有一個純虛函數(shù)。這是一種特殊的虛函數(shù),在抽象類中沒有具體實現(xiàn),而是留給派
生類去實現(xiàn)。
純虛函數(shù)的聲明方式是在函數(shù)聲明的末尾加上 = 0 。
2. 不能直接實例化:
由于抽象類不完整,所以不能直接創(chuàng)建它的對象。就像你不能直接使用“交通工具”的概念去任
何地方,你需要一個具體的交通工具。
3. 用于提供基礎(chǔ)結(jié)構(gòu):
抽象類的主要目的是為派生類提供一個共同的基礎(chǔ)結(jié)構(gòu),確保所有派生類都有一致的接口和行
為。
#include <iostream>
using namespace std;
class Teacher
{
public:
????????string name;
????????string shool;
????????string major;
????????virtual void goInClass() = 0;
????????virtual void startTeaching() = 0;
????????virtual void afterTeaching() = 0;
};
class EnglishTeacher : public Teacher
{
public:
????????void goInClass() override
????????{
????????????????cout << "英語老師開始進(jìn)入教室" << endl;
????????}
????????void startTeaching() override
????????{
????????????????cout << "英語老師開始教學(xué)" << endl;
????????}
????????void afterTeaching() override
????????{
????????};
};
class ProTeacher : public Teacher
{
public:
????????void goInClass() override
????????{
????????????????cout << "編程老師開始進(jìn)入教室" << endl;
????????}
????????void startTeaching() override
????????{
????????????????cout << "編程老師開始擼代碼了,拒絕讀PPT" << endl;
????????}
????????void afterTeaching() override
????????{
????????????????cout << "編程老師下課后手把手教x學(xué)員寫代碼" << endl;
????????};
};
int main()
{
????????// Teacher t;//抽象類,不支持被實例化
????????EnglishTeacher e;
????????e.goInClass();
????????ProTeacher t;
????????t.startTeaching();
????????t.afterTeaching();
????????//抽象類,多態(tài)
????????Teacher *teacher = new ProTeacher;
????????teacher->startTeaching();
????????return 0;
}
2.12 模版
在 C++ 中,模板(Template)是一種通用的編程工具,允許程序員編寫泛型代碼,使得類或函數(shù)能夠適用于多種不同的數(shù)據(jù)類型而不需要重復(fù)編寫相似的代碼。C++ 提供了兩種主要類型的模板:類模板和函數(shù)模板。
類模板(Class Templates):
類模板允許定義通用的類,其中某些類型可以作為參數(shù)。這樣的類可以處理不同類型的數(shù)據(jù),而不需要為每個數(shù)據(jù)類型編寫單獨的類。
#include <iostream>using namespace std;class PrintInt
{
private:int data;
public:void printInt(){cout << data <<endl;}void setInt(int data){this->data = data;}
};class PrintString
{
private:string data;
public:void printString(){cout << data <<endl;}void setString(string data){this->data = data;}
};template<typename T>
class PrintT
{
private:T data;
public:void printT(){cout << data <<endl;}void setT(T data){this->data = data;}
};int main()
{PrintInt p1;p1.setInt(10);p1.printInt();PrintString p2;p2.setString("chenzhuo");p2.printString();PrintT<int> p3;p3.setT(10);p3.printT();PrintT<string> p4;p4.setT("dashuaige");p4.printT();return 0;
}
?輸出