1. 程式人生 > >C++基礎教程面向物件(學習筆記(18))

C++基礎教程面向物件(學習筆記(18))

運算子過載簡介

您在前面學習了函式過載,它提供了一種具有相同名稱的多個函式的函式呼叫的建立和解析機制,只要每個函式都有一個唯一的函式原型。這允許您建立函式體以使用不同的資料型別,而無需為每個函式體考慮唯一的名稱。

在C ++中,運算子是作為函式實現的。通過在運算子函式上使用函式過載,您可以定義使用不同的資料型別的運算子版本(包括您編寫的類)。使用函式過載到過載運算子稱為運算子過載。

在本章中,我們將研究與運算子過載相關的主題。

運算子作為函式

請考慮以下示例:

int x = 2;
int y = 3;
std::cout << x + y << endl;

編譯器帶有一個用於整數運算元的加號運算子(+)的內建版本 - 該函式將整數x和y加在一起並返回整數結果。當您看到表示式時x + y,可以將其轉換為函式呼叫operator+(x, y)(其中operator +是函式的名稱)。

現在考慮這個類似的片段:

double z = 2.0;
double w = 3.0;
std::cout << w + z << endl;

編譯器還帶有一個內建版本的加法運算子(+),用於雙運算元。表示式w + z成為函式呼叫operator+(w, z),函式過載用於確定編譯器應該呼叫此函式的double版本而不是int版本。

現在考慮如果我們嘗試新增使用者定義類的兩個物件會發生什麼:

Mystring string1 = "Hello, ";
Mystring string2 = "World!";
std::cout << string1 + string2 << endl;

在這種情況下你會發生什麼?直觀的預期結果是字串“Hello,World!”將被列印在螢幕上。但是,因為Mystring是使用者定義的類,所以編譯器沒有可用於Mystring運算元的加法運算子的內建版本。所以在這種情況下,它會給我們丟擲一個錯誤。為了使它像我們想要的那樣工作,我們需要編寫一個過載函式來告訴編譯器+運算子應該如何使用兩個型別為Mystring的運算元。我們將在下一課中介紹如何執行此操作。

解決過載運算子

在評價包含運算子的表示式時,編譯器使用以下規則:

如果所有運算元都是基本資料型別,則編譯器將呼叫內建例程(如果存在)。如果不存在,編譯器將產生編譯器錯誤。 如果任何運算元是使用者資料型別(例如,您的某個類或列舉型別),編譯器將檢視該型別是否具有可以呼叫的匹配過載操作符函式。如果找不到,它將嘗試將一個或多個使用者定義的型別運算元轉換為基本資料型別,以便它可以使用匹配的內建運算子(通過過載的型別轉換,我們將在後面介紹這一章)。如果失敗,則會產生編譯錯誤。

運算子過載有哪些限制?

首先,幾乎所有C ++中的現有運算子都可以過載。例外情況是:條件(??,sizeof,範圍(:?,成員選擇器(.)和成員指標選擇器(.*)。

其次,您只能過載存在的運算子。您無法建立新運算子或重新命名現有運算子。例如,您無法建立運算子**來執行指數。

第三,過載運算子中的至少一個運算元必須是使用者定義的型別。這意味著你不能過載加號運算子來使用一個整數和一個double。但是,您可以過載加號運算子以使用整數和Mystring。

第四,不可能改變運營商支援的運算元的數量。

最後,所有運算子都保持其預設優先順序和關聯性(無論它們用於什麼),這都無法更改。

一些新程式設計師試圖使按位XOR運算子(^)過載以進行求冪。但是,在C ++中,operator ^的優先順序低於基本算術運算子,這會導致表示式的計算結果不正確。

在基礎數學中,取冪在基本算術之前解析,因此4 + 3 ^ 2解析為4 +(3 ^ 2)=> 4 + 9 => 13. 但是,在C ++中,算術運算子的優先順序高於運算子^,所以4 + 3 ^ 2解析為(4 + 3)^ 2 => 7 ^ 2 => 49。

每次使用它時,您都需要明確地將指數部分括起來(例如4 +(3 ^ 2)),以使其正常工作,這不直觀,並且可能容易出錯。

由於這個優先順序問題,通常只能以與原始意圖類似的方式使用運算子。

規則:當過載運算子時,最好保持運算子的功能儘可能接近運算子的原始意圖。

此外,由於運營商沒有描述性名稱,因此並不總是清楚他們打算做什麼。例如,operator +可能是字串類進行字串連線的合理選擇。但是運營商呢?你期望做什麼?目前還不清楚。

規則:如果應用於自定義類的運算子的含義不清晰直觀,請改用命名函式。

在這些範圍內,您仍然會發現許多有用的功能可以為您的自定義類過載!您可以過載+運算子以連線使用者定義的字串類,或者將兩個Fraction類物件一起新增。您可以過載<<運算子,以便將類列印到螢幕(或檔案)。您可以過載相等運算子(==)以比較兩個類物件。這使得運算子過載C ++中最有用的功能之一 - 只是因為它允許您以更直觀的方式使用類。

在即將到來的課程中,我們將深入研究超載不同型別的運營商。