日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

C++ 面向对象(二)—— 操作符重载

發(fā)布時間:2023/12/9 c/c++ 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C++ 面向对象(二)—— 操作符重载 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

C++ 實現(xiàn)了在類(class)之間使用語言標準操作符,而不只是在基本數(shù)據(jù)類型之間使用。例如:

int a, b, c;
a = b + c;

是有效操作,因為加號兩邊的變量都是基本數(shù)據(jù)類型。然而,我們是否可以進行下面的操作就不是那么顯而易見了(它實際上是正確的):

struct { char product [50]; float price; } a, b, c;
a = b + c;

將一個類class (或結(jié)構(gòu)struct)的對象賦給另一個同種類型的對象是允許的(通過使用默認的復制構(gòu)造函數(shù) copy constructor)。但相加操作就有可能產(chǎn)生錯誤,理論上講它在非基本數(shù)據(jù)類型之間是無效的。

但歸功于C++ 的操作符重載(overload)能力,我們可以完成這個操作。像以上例子中這樣的組合類型的對象在C++中可以接受如果沒有操作符重載則不能被接受的操作,我們甚至可以修改這些操作符的效果。以下是所有可以被重載的操作符的列表:

+ - * / = < > += -= *= /= << >><<= >>= == != <= >= ++ -- % & ^ ! |~ &= ^= |= && || %= [] () new delete

要想重載一個操作符,我們只需要編寫一個成員函數(shù),名為operator ,后面跟我們要重載的操作符,遵循以下原型定義:

type operator sign (parameters);

這里是一個操作符 +的例子。我們要計算二維向量(bidimensional vector) a(3,1) 與b(1,2)的和。兩個二維向量相加的操作很簡單,就是將兩個x 軸的值相加獲得結(jié)果的x 軸值,將兩個 y 軸值相加獲得結(jié)果的 y值。在這個例子里,結(jié)果是 (3+1,1+2) = (4,3)。

// vectors: overloading operators example#include <iostream.h>class CVector {public:int x,y;CVector () {};CVector (int,int);CVector operator + (CVector);};CVector::CVector (int a, int b) {x = a;y = b;}CVector CVector::operator+ (CVector param) {CVector temp;temp.x = x + param.x;temp.y = y + param.y;return (temp);}int main () {CVector a (3,1);CVector b (1,2);CVector c;c = a + b;cout << c.x << "," << c.y;return 0;} 4,3

如果你迷惑為什么看到這么多遍的 CVector,那是因為其中有些是指class名稱CVector ,而另一些是以它命名的函數(shù)名稱,不要把它們搞混了:

CVector (int, int); // 函數(shù)名稱 CVector (constructor)CVector operator+ (CVector); // 函數(shù) operator+ 返回CVector 類型的值

Class CVector的函數(shù) operator+ 是對數(shù)學操作符+進行重載的函數(shù)。這個函數(shù)可以用以下兩種方法進行調(diào)用:

c = a + b;
c = a.operator+ (b);

注意:我們在這個例子中包括了一個空構(gòu)造函數(shù) (無參數(shù)),而且我們將它定義為無任何操作:

CVector ( ) { };

這是很必要的,因為例子中已經(jīng)有另一個構(gòu)造函數(shù),

CVector (int, int);

因此,如果我們不像上面這樣明確定義一個的話,CVector的兩個默認構(gòu)造函數(shù)都不存在。

這樣的話,main( )中包含的語句

CVector c;

將為不合法的。

盡管如此,我已經(jīng)警告過一個空語句塊 (no-op block)并不是一種值得推薦的構(gòu)造函數(shù)的實現(xiàn)方式,因為它不能實現(xiàn)一個構(gòu)造函數(shù)至少應(yīng)該完成的基本功能,也就是初始化class中的所有變量。在我們的例子中,這個構(gòu)造函數(shù)沒有完成對變量x 和 y 的定義。因此一個更值得推薦的構(gòu)造函數(shù)定義應(yīng)該像下面這樣:

CVector ( ) { x=0; y=0; };

就像一個class默認包含一個空構(gòu)造函數(shù)和一個復制構(gòu)造函數(shù)一樣,它同時包含一個對賦值操作符assignation operator (=)的默認定義,該操作符用于兩個同類對象之間。這個操作符將其參數(shù)對象(符號右邊的對象) 的所有非靜態(tài) (non-static) 數(shù)據(jù)成員復制給其左邊的對象。當然,你也可以將它重新定義為你想要的任何功能,例如,只拷貝某些特定class成員。

重載一個操作符并不要求保持其常規(guī)的數(shù)學含義,雖然這是推薦的。例如,雖然我們可以將操作符+定義為取兩個對象的差值,或用==操作符將一個對象賦為0,但這樣做是沒有什么邏輯意義的。

雖然函數(shù)operator+ 的原型定義看起來很明顯,因為它取操作符右邊的對象為其左邊對象的函數(shù)operator+的參數(shù),其它的操作符就不一定這么明顯了。以下列表總結(jié)了不同的操作符函數(shù)是怎樣定義聲明的 (用操作符替換每個@):

ExpressionOperator (@)Function memberGlobal function
@a+ - * & ! ~ ++ --A::operator@( )operator@(A)
a@++ --A::operator@(int)operator@(A, int)
a@b+ - * / % ^ & | < > == != <= >= << >> && || ,A::operator@(B)operator@(A, B)
a@b= += -= *= /= %= ^= &= |= <<= >>= [ ]A::operator@(B)-
a(b, c...)( )A::operator()(B, C...)-
a->b->A::operator->()-

* 這里a 是class A的一個對象,b 是 B 的一個對象,c 是class C 的一個對象。

從上表可以看出有兩種方法重載一些class操作符:作為成員函數(shù)(member function)或作為全域函數(shù)(global function)。它們的用法沒有區(qū)別,但是我要提醒你,如果不是class的成員函數(shù),則不能訪問該class的private 或 protected 成員,除非這個全域函數(shù)是該class的 friend (friend 的含義將在后面的章節(jié)解釋)。


關(guān)鍵字 this

關(guān)鍵字this 通常被用在一個class內(nèi)部,指正在被執(zhí)行的該class的對象(object)在內(nèi)存中的地址。它是一個指針,其值永遠是自身object的地址。

它可以被用來檢查傳入一個對象的成員函數(shù)的參數(shù)是否是該對象本身。例如:

// this#include <iostream.h>class CDummy {public:int isitme (CDummy& param);};int CDummy::isitme (CDummy& param) {if (&param == this) return 1;else return 0;}int main () {CDummy a;CDummy* b = &a;if ( b->isitme(a) )cout << "yes, &a is b";return 0;} yes, &a is b

它還經(jīng)常被用在成員函數(shù)operator= 中,用來返回對象的指針(避免使用臨時對象)。以下用前面看到的向量(vector)的例子來看一下函數(shù)operator= 是怎樣實現(xiàn)的:

CVector& CVector::operator= (const CVector& param) {x=param.x;y=param.y;return *this;}

實際上,如果我們沒有定義成員函數(shù)operator=,編譯器自動為該class生成的默認代碼有可能就是這個樣子的。


靜態(tài)成員(Static members)

一個class 可以包含靜態(tài)成員(static members),可以是數(shù)據(jù),也可以是函數(shù)。

一個class的靜態(tài)數(shù)據(jù)成員也被稱作類變量"class variables",因為它們的內(nèi)容不依賴于某個對象,對同一個class的所有object具有相同的值。

例如,它可以被用作計算一個class聲明的objects的個數(shù),見以下代碼程序:

// static members in classes#include <iostream.h>class CDummy {public:static int n;CDummy () { n++; };~CDummy () { n--; };};int CDummy::n=0;int main () {CDummy a;CDummy b[5];CDummy * c = new CDummy;cout << a.n << endl;delete c;cout << CDummy::n << endl;return 0;} 7
6

實際上,靜態(tài)成員與全域變量(global variable)具有相同的屬性,但它享有類(class)的范圍。因此,根據(jù)ANSI-C++ 標準,為了避免它們被多次重復聲明,在class的聲明中只能夠包括static member的原型(聲明),而不能夠包括其定義(初始化操作)。為了初始化一個靜態(tài)數(shù)據(jù)成員,我們必須在class之外(在全域范圍內(nèi)),包括一個正式的定義,就像上面例子中做法一樣。

因為它對同一個class的所有object是同一個值,所以它可以被作為該class的任何object的成員所引用,或者直接被作為class的成員引用(當然這只適用于static 成員):

cout << a.n;
cout << CDummy::n;

以上兩個調(diào)用都指同一個變量:class CDummy里的static 變量 n 。

在提醒一次,它其實是一個全域變量。唯一的不同是它的名字跟在class的后面。

就像我們會在class中包含static數(shù)據(jù)一樣,我們也可以使它包含static 函數(shù)。它們表示相同的含義:static函數(shù)是全域函數(shù)(global functions),但是像一個指定class的對象成員一樣被調(diào)用。它們只能夠引用static 數(shù)據(jù),永遠不能引用class的非靜態(tài)(nonstatic)成員。它們也不能夠使用關(guān)鍵字this,因為this實際引用了一個對象指針,但這些 static函數(shù)卻不是任何object的成員,而是class的直接成員。

總結(jié)

以上是生活随笔為你收集整理的C++ 面向对象(二)—— 操作符重载的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。