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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

C++学习笔记:(四)运算符重载 类型转换

發(fā)布時(shí)間:2024/2/28 c/c++ 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C++学习笔记:(四)运算符重载 类型转换 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

目錄

6.運(yùn)算符重載

6.1運(yùn)算符重載的基本概念

6.2成員函數(shù)重載運(yùn)算符

6.3友元函數(shù)重載運(yùn)算符

6.4成員函數(shù)重載運(yùn)算符和友元函數(shù)重載運(yùn)算符比較

6.5類型轉(zhuǎn)換


6.運(yùn)算符重載

面向?qū)ο蟪绦蛟O(shè)計(jì)的重載有函數(shù)重載和運(yùn)算符重載。函數(shù)重載是指在相同作用域內(nèi),若干個(gè)參數(shù)特征不同的函數(shù)使用相同的函數(shù)名,也稱為函數(shù)名重載;運(yùn)算符重載是另一種調(diào)用函數(shù)的方法,是指同樣的運(yùn)算符可以施加于不同類型的操作數(shù)上面,也就是對已有的運(yùn)算符賦予多重含義,使同一個(gè)運(yùn)算符作用于不同類型的數(shù)據(jù)時(shí)產(chǎn)生不同的行為,是一種靜態(tài)聯(lián)編的多態(tài)。

?

6.1運(yùn)算符重載的基本概念

與函數(shù)重載相似,運(yùn)算符也存在重載問題。C++語言預(yù)定義的運(yùn)算符只適用于基本數(shù)據(jù)類型。為了解決一些實(shí)際問題,程序員經(jīng)常會(huì)定義一些新類型,即自定義類型,然而C++不允許生成新的運(yùn)算符,因此為了實(shí)現(xiàn)對自定義類型的操作,就必須自己來編寫函數(shù)說明某個(gè)運(yùn)算符如何作用于這些數(shù)據(jù)類型,這樣的程序可讀性較差。針對這種情況,C++允許重載現(xiàn)有的大多數(shù)運(yùn)算符,也就是允許給已有的運(yùn)算符賦予新的含義,從而提高了C++的可擴(kuò)展性,使得針對同樣的操作,使用重載運(yùn)算符比使用顯式函數(shù)調(diào)用更能提高程序的可讀性。

C++語言對運(yùn)算符重載進(jìn)行了以下規(guī)定限制:

(1)只能重載C++語言中原先已定義的運(yùn)算符,不能自己創(chuàng)造新的運(yùn)算符進(jìn)行重載。

(2)并不是所有的運(yùn)算符都可以重載。不能進(jìn)行重載的運(yùn)算符:.?.*?::??:

(3)不能改變運(yùn)算符原有的優(yōu)先級(jí)和結(jié)合性。

(4)不能改變運(yùn)算符對預(yù)定義類型數(shù)據(jù)的操作方式,但是可以根據(jù)實(shí)際需要,對原有運(yùn)算符進(jìn)行適當(dāng)?shù)母脑旌蛿U(kuò)充。

(5)運(yùn)算符重載有兩種方式:重載為類的成員函數(shù)&重載為類的友元函數(shù)。

?

6.2成員函數(shù)重載運(yùn)算符

成員函數(shù)重載運(yùn)算符的原型在類的內(nèi)部

class 類名 {...返回類型 operator 運(yùn)算符(形參表) }; 在類外定義成員運(yùn)算符函數(shù)的格式: 返回類型 類名::operator 運(yùn)算符(形參表) {//函數(shù)體 }

返回類型是指運(yùn)算符重載函數(shù)的運(yùn)算結(jié)果類型;operator是定義運(yùn)算符重載函數(shù)的關(guān)鍵字;運(yùn)算符是要重載的運(yùn)算符名稱;形參表中給出了重載運(yùn)算符所需要的參數(shù)和類型。

?

6.2.1單目運(yùn)算符重載

用成員函數(shù)重載運(yùn)算符時(shí),如果運(yùn)算符是單目的,則參數(shù)表為空。因?yàn)檫@時(shí)操作數(shù)訪問該重載運(yùn)算符的對象本身的數(shù)據(jù),該對象有this指針指向,所以參數(shù)表為空。

單目運(yùn)算賦的調(diào)用有兩種方式:顯式調(diào)用和隱式調(diào)用。

(1)顯式:對象名.operator 運(yùn)算符()

(2)隱式:重載的運(yùn)算符 對象名

重載”-”運(yùn)算符:

#include <iostream> #include <iomanip> using namespace std;class Point {private:int x,y;public:Point(int i = 0, int j = 0);Point operator -(); void Print();};Point::Point(int i, int j) {x = i;y = j; }void Point::Print() {cout << "x=" << x << setw(5) << "y=" << y <<endl; }Point Point::operator -() {x = -x;y = -y;return *this; }int main() {Point ob1(1, 2);cout << "ob1:" <<endl;ob1.Print();cout << "-ob1:" <<endl;ob1.operator -(); //顯式調(diào)用//ob = -ob1; //隱式調(diào)用ob1.Print();return 0; }

在進(jìn)行重載時(shí),函數(shù)沒有接收參數(shù),運(yùn)算符后的操作數(shù)有this指針指出。語句x = -x; y = -y;相當(dāng)于this->x = -this->x; this->y = -this->y;。

?

6.2.2雙目運(yùn)算符重載

重載雙目運(yùn)算符時(shí),左邊操作數(shù)是訪問該重載運(yùn)算符的對象本身的數(shù)據(jù),有this指針指向,右邊操作數(shù)通過成員運(yùn)算符函數(shù)的參數(shù)指出。所以,此時(shí)成員運(yùn)算符函數(shù)只有一個(gè)參數(shù)。

雙目運(yùn)算賦的調(diào)用有兩種方式:顯式調(diào)用和隱式調(diào)用。

(1)顯式:對象名.operator 運(yùn)算符()

(2)隱式:對象名 重載的運(yùn)算符 參數(shù)

重載”+”運(yùn)算符,實(shí)現(xiàn)兩個(gè)字符串相加:

#include <iostream> #include <string.h> using namespace std; const int Max = 20; class String {private:char buffer[Max];int length;public:String(char *in_str);String();String operator +(char *append_str);void showstring(); };String::String(char *in_str) {strcpy(buffer, in_str);length = strlen(buffer); }String::String() {length = 0; }String String::operator +(char *append_str) {String temp;int templen;templen = strlen(buffer)+strlen(append_str)+1;if(templen > Max){cout << "String is too large!" <<endl;strcpy(temp.buffer, buffer);return temp;}length = templen;strcpy(temp.buffer, buffer);strcat(temp.buffer, append_str);return temp; }void String::showstring() {cout << buffer <<endl; }int main() {String title((char*)"C/C++ ");title = title + (char*)"Program"; //隱式調(diào)用//title = title.operator+("Program"); //顯式調(diào)用,不加char*會(huì)出現(xiàn)警告title.showstring();return 0; }

在執(zhí)行語句title = title + “Program”;時(shí),編譯系統(tǒng)首先將title+”Program”解釋為title.operator+(“Program”),從而調(diào)用運(yùn)算符重載函數(shù)operator+(char*append_str)實(shí)現(xiàn)字符串的相加。最后再將運(yùn)算符重載函數(shù)的返回值賦給title。在進(jìn)行重載時(shí),函數(shù)只接受一個(gè)參數(shù),該參數(shù)是運(yùn)算符的第二個(gè)參數(shù),第一個(gè)參數(shù)由this指針指向。語句strcpy(temp.buffer, buffer);相當(dāng)于strcpy(temp.buffer, this->buffer);。

用成員函數(shù)重載運(yùn)算符實(shí)現(xiàn)復(fù)數(shù)的加、減運(yùn)算:

#include <iostream> using namespace std;class Complex {private:double real,imag;public:Complex(double r = 0.0, double i = 0.0);void Print();Complex operator+(Complex a);Complex operator-(Complex a);};Complex::Complex(double r, double i) {real = r;imag = i; }Complex Complex::operator+(Complex a) {Complex temp;temp.real = real + a.real;temp.imag = imag + a.imag;return temp; }Complex Complex::operator-(Complex a) {Complex temp;temp.real = real - a.real;temp.imag = imag - a.imag;return temp; }void Complex::Print() {cout <<real;if(imag > 0)cout << "+";if(imag != 0)cout << imag << "i" <<endl; }int main() {Complex c1(1.1, 2.2), c2(3.3, 4.4),total;total = c1 + c2;total.Print();total = c1 - c2;total.Print();return 0; }

?

6.2.3重載++、--運(yùn)算符

現(xiàn)在C++能識(shí)別”++”、”--”運(yùn)算符是前綴的還是后綴的,它們是單目運(yùn)算符,分為前綴和后綴兩種。

類名 operator ++() ?????//前綴方式

類名 operator ++(int) ???//后綴方式

類名 operator --() ??????//前綴方式

類名 operator --(int) ????//后綴方式

重載”++”&”--”運(yùn)算符:

#include <iostream> #include <iomanip> using namespace std;class Point {private:int x,y;public:Point(int i = 0, int j = 0);Point operator++();Point operator--(); Point operator++(int); Point operator--(int); void Print();};Point::Point(int i, int j) {x = i;y = j; }void Point::Print() {cout << "(" << x << "," << y << ")" <<endl; }Point Point::operator--() {--x;--y;return *this; } Point Point::operator++() {++x;++y;return *this; } Point Point::operator--(int) {Point temp = *this;x--;y--;return temp; } Point Point::operator++(int) {Point temp = *this;x++;y++;return temp; }int main() {Point ob1(1, 2), ob2(3, 4), ob;cout << "ob1:";ob1.Print();cout << "++ob1: ";++ob1;cout << "ob1:";ob1.Print();cout << "ob2:";ob2.Print();cout << "--ob2: ";--ob2;cout << "bo2: ";ob2.Print();cout << "ob = ob1++" <<endl;ob = ob1++;cout << "ob: ";ob.Print();cout << "ob1: ";ob1.Print();cout << "ob = ob1-- " <<endl; ob = ob--;cout << "ob: ";ob.Print();cout << "ob1: ";ob1.Print();return 0; }

?

6.2.4重載賦值運(yùn)算符

C++中,對于任何一個(gè)類,如果沒有用戶自定義的賦值運(yùn)算符函數(shù),系統(tǒng)會(huì)自動(dòng)地為其生成一個(gè)默認(rèn)的賦值運(yùn)算符函數(shù),以完成數(shù)據(jù)成員之間的復(fù)制。通常情況下,默認(rèn)的賦值運(yùn)算符函數(shù)可以完成賦值任務(wù),但在某些特殊情況下,如類中有指針的情況下,就不能進(jìn)行直接賦值。

指針懸掛問題:

#include <iostream> #include <iomanip> #include <string.h> using namespace std; class Student {private:char *name;float score;public:Student(char *na, float sco);~Student(); void Print(); };Student::Student(char *na, float sco) {name = new char[strlen(na)+1];strcpy(name, na);score = sco; }Student::~Student() {delete name; }void Student::Print() {cout << "student:" << name << " " << "Score:" << score <<endl; }int main() {Student p1((char*)"zhangming", 90.5);p1.Print();Student p2((char*)"wanglan", 95);p2.Print();p2 = p1;cout << "p2:";p2.Print();return 0; }

程序運(yùn)行結(jié)果出錯(cuò)的原因是當(dāng)執(zhí)行賦值語句p2 = p1時(shí),這時(shí)p2和p1里的name指針指向了同一個(gè)空間,當(dāng)對象p1和p2的生存期結(jié)束時(shí),系統(tǒng)將調(diào)用析構(gòu)函數(shù)釋放空間,因?yàn)橹挥幸粋€(gè)空間,所以只能釋放一次,另一個(gè)指針?biāo)傅目臻g就不存在了,產(chǎn)生了指針懸掛。

解決:

#include <iostream> #include <iomanip> #include <string.h> using namespace std; class Student {private:char *name;float score;public:Student(char *na, float sco);Student &operator=(const Student &); ~Student(); void Print(); };Student::Student(char *na, float sco) {name = new char[strlen(na)+1];strcpy(name, na);score = sco; }Student::~Student() {delete name; }Student & Student::operator=(const Student &p) {if(this == &p)return *this;delete name;name = new char[strlen(p.name)+1];strcpy(name, p.name);return *this; }void Student::Print() {cout << "student:" << name << " " << "Score:" << score <<endl; }int main() {Student p1((char*)"zhangming", 90.5);Student p2((char*)"wanglan", 95);cout << "p2:" ;p2.Print();p2 = p1;cout << "p2:";p2.Print();return 0; }

注意:(1)賦值運(yùn)算符不能重載為友元函數(shù),只能重載為一個(gè)非靜態(tài)成員函數(shù)。

(2)賦值運(yùn)算符重載函數(shù)不能被繼承。

?

重載”+=”運(yùn)算符,實(shí)現(xiàn)的是字符串的連接運(yùn)算:

#include <iostream> #include <string.h> using namespace std;class String {private:char *buffer;int length;public:String(char *in_str);const String &operator+=(const String &);void showstring();~String(); };String::String(char *in_str) {length = strlen(in_str);buffer = new char[length+1];strcpy(buffer, in_str); }const String & String::operator+=(const String &append_str) {char *temp = buffer;length += append_str.length;buffer = new char[length+1];strcpy(buffer, temp);strcat(buffer, append_str.buffer);delete[]temp;return *this; }void String::showstring() {cout << buffer <<endl; }String::~String() {delete []buffer; }int main() {String s1((char*)"happy"),s2((char*)" birthday");s1 += s2;s1.showstring();s1 += (char*)" to you";s1.showstring();return 0; }

?

6.2.5重載下標(biāo)運(yùn)算符

當(dāng)程序變得更為復(fù)雜時(shí),有時(shí)必須重載數(shù)組下標(biāo)運(yùn)算符[],C++重載數(shù)組運(yùn)算符時(shí)認(rèn)為它是雙目運(yùn)算符,因此重載數(shù)組下標(biāo)運(yùn)算符[]時(shí),運(yùn)算符成員函數(shù)的形式:

返回類型 ?類名::operator[] (形參) {//函數(shù)體 }

重載下標(biāo)運(yùn)算符,用一維數(shù)組實(shí)現(xiàn)一個(gè)三維向量類:

#include <iostream> using namespace std;class Vector {private:int v[3];public:Vector(int a1, int a2, int a3);int &operator[](int bi); };Vector::Vector(int a1, int a2, int a3) {v[0] = a1;v[1] = a2;v[2] = a3; }int & Vector::operator[](int bi) {if(bi < 0 || bi >= 3){cout << "Bad subscript!" <<endl;exit(1);}return v[bi]; }int main() {int i;Vector v(1, 3, 5);cout << "Befor:" <<endl;for(i = 0; i < 3; i++)cout << v[i] << " ";cout <<endl;cout << "After:" <<endl;for(i = 0; i < 3; i++)v[i] = 3*i;for(i = 0; i < 3; i++)cout << v[i] <<" ";cout <<endl;return 0; }

程序執(zhí)行語句cout << v[i] << setw(4)時(shí),編譯系統(tǒng)將v[i]解釋為v.operator[](i),從而調(diào)用運(yùn)算符重載函數(shù)operator [](int bi)。在函數(shù)中首先判斷數(shù)組下標(biāo)的值是否越界,如果越界,則顯示相應(yīng)的錯(cuò)誤信息,否則返回下標(biāo)所對應(yīng)的元素的值。在定義重載[]函數(shù)時(shí),由于返回是一個(gè)int的引用,因此可以使重載的[]用在賦值語句的左邊,所以語句v[i] = 2*i是合法的,從而使程序更加靈活。

注意:(1)重載下標(biāo)運(yùn)算符[]的一個(gè)優(yōu)點(diǎn)是,可以增加C++中數(shù)組檢索的安全性。

(2)重載下標(biāo)運(yùn)算符[]時(shí),返回一個(gè)int的引用,可使重載的[]用在賦值語句的左邊,因而在main函數(shù)中,v[i]可以出現(xiàn)在賦值運(yùn)算符的任何一邊,使編程更靈活。

?

6.2.6重載函數(shù)調(diào)用運(yùn)算符”()”

重載函數(shù)調(diào)用運(yùn)算符()時(shí),并不是創(chuàng)建新的調(diào)用函數(shù)的方法,而是創(chuàng)建了可傳遞任意數(shù)目參數(shù)的運(yùn)算符函數(shù),通常重載函數(shù)調(diào)用運(yùn)算符()時(shí),定義了傳遞給重載函數(shù)的參數(shù)。重載函數(shù)調(diào)用運(yùn)算符()成員函數(shù)的形式:

返回類型 ?類名::operator()(形參) {//函數(shù)體 }

重載函數(shù)調(diào)用運(yùn)算符”()”:

#include <iostream> using namespace std;class Mat {private:int *m;int row,col;public:Mat(int, int);int &operator()(int, int); };Mat::Mat(int r, int c) {row = r;col = c;m = new int[row*col];for(int i = 0; i < row*col; i++){*(m+i) = i;} }int &Mat::operator()(int r, int c) {return (*(m+r*col+c)); }int main() {Mat aM(10, 10);cout << aM(3, 4) <<endl;aM(3, 4) = 35;cout << aM(3, 4) <<endl;return 0; }

在執(zhí)行語句cout << aM(3, 4) <<endl;時(shí),編譯系統(tǒng)將aM(3, 4)解釋為aM.operator()(3, 4),從而調(diào)用運(yùn)算符重載函數(shù)operatori()(int r, int c),然后返回矩陣第3行第4列的元素的值。語句aM(3, 4) = 35;修改矩陣第3行第4列的元素的值,之所以能夠這樣寫,是因?yàn)楹瘮?shù)operator()返回的是引用類型int&的緣故。

?

6.3友元函數(shù)重載運(yùn)算符

大多數(shù)情況下用友元函數(shù)或用成員函數(shù)重載運(yùn)算符,在功能上是沒有差別的。用友元函數(shù)重載運(yùn)算符時(shí),因?yàn)橛言\(yùn)算符函數(shù)沒有this指針,所以如果運(yùn)算符時(shí)單目的,則參數(shù)表中有一個(gè)操作數(shù),如果運(yùn)算符時(shí)雙目的,則參數(shù)表中有兩個(gè)操作數(shù)。其形式:

friend <函數(shù)類型>operator<重載的運(yùn)算符>(<形參>) ?????????//單目運(yùn)算符重載 {...} friend <函數(shù)類型>operator<重載的運(yùn)算符>(<形參1>,<形參2>) //雙目運(yùn)算符重載 {...}

用友元函數(shù)重載運(yùn)算符實(shí)現(xiàn)復(fù)數(shù)的加、減運(yùn)算:

#include <iostream> using namespace std;class Complex {private:double real,imag;public:Complex(double r = 0.0, double i = 0.0);void Print();friend Complex operator+(Complex a, Complex b);friend Complex operator-(Complex a, Complex b); };Complex::Complex(double r, double i) {real = r;imag = i; }Complex operator+(Complex a, Complex b) {Complex temp;temp.real = b.real + a.real;temp.imag = b.imag + a.imag;return temp; }Complex operator-(Complex a, Complex b) {Complex temp;temp.real = b.real - a.real;temp.imag = b.imag - a.imag;return temp; }void Complex::Print() {cout <<real;if(imag > 0)cout << "+";if(imag != 0)cout << imag << "i" <<endl; }int main() {Complex c1(1.1, 2.2), c2(3.3, 4.4),total;total = c1 + c2;total.Print();total = c1 - c2;total.Print();return 0; }

重載單目運(yùn)算符”-”:

#include <iostream> using namespace std;class Point {private:int x,y;public:Point(int i = 0, int j = 0);friend Point operator-(Point ob); void Print();};Point::Point(int i, int j) {x = i;y = j; }void Point::Print() {cout << "(" << x << "," << y << ")" <<endl; }Point operator-(Point ob) {ob.x = -ob.x;ob.y = -ob.y;return ob; }int main() {Point ob1(1, 2), ob2(3, 4), ob;cout << "ob1:";ob1.Print();cout << "-ob1: ";ob2 = -ob1; ob2.Print();return 0; }

重載”++”運(yùn)算符:

#include <iostream> using namespace std;class Point {private:int x,y;public:Point(int i = 0, int j = 0);friend Point operator++(Point ob);void Print();};Point::Point(int i, int j) {x = i;y = j; }void Point::Print() {cout << "(" << x << "," << y << ")" <<endl; }Point operator++(Point ob) {++ob.x;++ob.y;return ob; }int main() {Point ob1(1, 2), ob2;cout << "ob1:" <<endl;ob1.Print();ob2 = ++ob1;cout << "++ob1: " <<endl;ob1.Print();cout << "ob2:" <<endl;ob2.Print();return 0; }

這個(gè)運(yùn)行結(jié)果與所希望的運(yùn)行結(jié)果不一致,產(chǎn)生不一致的原因在于友元函數(shù)沒有this指針,所以不能引用this指針?biāo)傅膶ο蟆_@個(gè)函數(shù)采用對象參數(shù)通過傳值的方法傳遞參數(shù),函數(shù)體內(nèi)對ob的所有修改都不會(huì)傳到函數(shù)體外。因此,對象x和對象y并未增加,所以沒有輸出所希望的結(jié)果。解決這個(gè)問題有兩個(gè)方法:一是采用引用參數(shù)傳遞操作數(shù);二是用成員運(yùn)算符函數(shù)進(jìn)行重載。

引用參數(shù)傳遞操作數(shù):

#include <iostream> using namespace std;class Point {private:int x,y;public:Point(int i = 0, int j = 0);friend Point operator++(Point &ob);void Print();};Point::Point(int i, int j) {x = i;y = j; }void Point::Print() {cout << "(" << x << "," << y << ")" <<endl; }Point operator++(Point &ob) {++ob.x;++ob.y;return ob; }int main() {Point ob1(1, 2), ob2;cout << "ob1:" <<endl;ob1.Print();ob2 = ++ob1;cout << "++ob1: " <<endl;ob1.Print();cout << "ob2:" <<endl;ob2.Print();return 0; }

?

6.4成員函數(shù)重載運(yùn)算符和友元函數(shù)重載運(yùn)算符比較

在進(jìn)行運(yùn)算符重載時(shí),既可以是成員函數(shù)重載也可以是友元函數(shù)重載。下面是成員函數(shù)重載運(yùn)算符與友元函數(shù)重載運(yùn)算符的比較

(1)雙目運(yùn)算符,成員函數(shù)重載運(yùn)算符帶有一個(gè)參數(shù),而友元函數(shù)重載運(yùn)算符帶有兩個(gè)參數(shù);單目運(yùn)算符,成員函數(shù)重載運(yùn)算符不帶參數(shù),而友元函數(shù)重載運(yùn)算符帶有一個(gè)參數(shù)。

(2)雙目運(yùn)算符一般可以被重載為友元運(yùn)算符或成員運(yùn)算符函數(shù),下面的情況必須使用友元函數(shù)。

例如:用成員函數(shù)重載運(yùn)算符”+”。

Complex Complex::operator +(int a) {Complex temp;temp.real = real + a;temp.imag = imag + a;return temp; }

如果類Complex的對象com要做賦值運(yùn)算和加法運(yùn)算,下面的語句時(shí)正確的。

com = com + 10;

這是因?yàn)閷ο骳om是運(yùn)算符”+”的做操作數(shù),在調(diào)用重載運(yùn)算符”+”的函數(shù)時(shí),this指針指向com。因此語句temp.real = real + a;相當(dāng)于temp.real = this->real + a;。而下面的語句就不正確了。

com = 10 + com;

這是因?yàn)樽蟛僮鲾?shù)是一個(gè)整數(shù),而整數(shù)是一個(gè)內(nèi)部數(shù)據(jù)類型,不能產(chǎn)生對成員運(yùn)算符函數(shù)的調(diào)用。解決這類問題的方法是采用兩個(gè)友元函數(shù)來重載運(yùn)算符函數(shù)+,從而消除運(yùn)算符+的左操作數(shù)是內(nèi)部數(shù)據(jù)類型而帶來的問題。

用友元函數(shù)重載運(yùn)算符”+”:

#include <iostream> using namespace std;class Complex {private:double real,imag;public:Complex(double r = 0.0, double i = 0.0);void Print();friend Complex operator+(Complex a, int c);friend Complex operator+(int c, Complex a); };Complex::Complex(double r, double i) {real = r;imag = i; }Complex operator+(Complex a, int c) {Complex temp;temp.real = a.real + c;temp.imag = a.imag + c;return temp; }Complex operator+(int c, Complex a) {Complex temp;temp.real = c + a.real;temp.imag = c + a.imag;return temp; }void Complex::Print() {cout <<real;if(imag > 0)cout << "+";if(imag != 0)cout << imag << "i" <<endl; }int main() {Complex com(1.1, 2.2);com = com + 10;cout << "com + 10" <<endl;com.Print();cout << "10 + com" <<endl;com = 10 + com;com.Print(); return 0; }

一般而言,對于雙目運(yùn)算符,將它重載為友元運(yùn)算符函數(shù)比重載為成員運(yùn)算符函數(shù)便于使用。如果一個(gè)運(yùn)算符的操作需要修改類對象的狀態(tài),建議使用成員運(yùn)算符函數(shù);如果運(yùn)算符所需的操作數(shù)(尤其是第一個(gè)操作數(shù))希望有隱式類型轉(zhuǎn)換,則運(yùn)算符必須用友元函數(shù),而不能用成員函數(shù)。

對于單目運(yùn)算符,建議選擇成員函數(shù);

對于運(yùn)算符=、()、[],建議選擇成員函數(shù);

對于運(yùn)算符+=、-=、/=、*=、&=、!=、~=、%=、>>=、<<=,建議重載為成員函數(shù)。

其他運(yùn)算符,建議重載為友元函數(shù)。

?

6.5類型轉(zhuǎn)換

大多數(shù)程序都可以處理各種數(shù)據(jù)類型的信息,有時(shí)所有操作會(huì)集中在同一類型。例如,整數(shù)加整數(shù)還是整數(shù)(結(jié)果不超出整數(shù)的表示范圍)。但是,在很多情況下都需要將一種類型的數(shù)據(jù)轉(zhuǎn)換為另一種類型的數(shù)據(jù)。例如,在進(jìn)行賦值、計(jì)算、向函數(shù)傳值及函數(shù)返回值等,都有可能發(fā)生這種情況。對于內(nèi)部類型(基本類型、預(yù)定義類型),編譯器知道如何進(jìn)行類型轉(zhuǎn)換。程序員也可以用強(qiáng)制類型轉(zhuǎn)換實(shí)現(xiàn)內(nèi)部類型的強(qiáng)制轉(zhuǎn)換。

?

6.5.1系統(tǒng)預(yù)定義類型之間的轉(zhuǎn)換

C++規(guī)定,當(dāng)不同類型的數(shù)據(jù)進(jìn)行運(yùn)算時(shí),需先將數(shù)據(jù)轉(zhuǎn)換成同一類型,然后才可以進(jìn)行運(yùn)算。數(shù)據(jù)的類型轉(zhuǎn)換可以通過兩種轉(zhuǎn)換形式完成:一種是隱式類型轉(zhuǎn)換,另一種是顯式類型轉(zhuǎn)換。

隱式轉(zhuǎn)換:

當(dāng)執(zhí)行賦值表達(dá)式V=E時(shí),如果V和E的類型不一致,則將E先轉(zhuǎn)換為V后再賦值。與C語言一樣,C++中規(guī)定數(shù)據(jù)類型級(jí)別從高到低的次序是:double->float->long int->int->short、char。當(dāng)兩個(gè)操作數(shù)類型不一致時(shí),運(yùn)算之前將級(jí)別低的自動(dòng)轉(zhuǎn)換為級(jí)別高的,然后再進(jìn)行運(yùn)算。例如,當(dāng)char或short類型數(shù)據(jù)與int類型數(shù)據(jù)進(jìn)行運(yùn)算時(shí),把char或short類型數(shù)據(jù)轉(zhuǎn)換成int類型數(shù)據(jù)。

顯式轉(zhuǎn)換:

①強(qiáng)制轉(zhuǎn)換法:(類型名)表達(dá)式 ??(float)(5%2)

②函數(shù)法:類型名(表達(dá)式) ??float (a+b);

以上介紹的是一般數(shù)據(jù)類型之間的轉(zhuǎn)換。如果用戶自定義類型,如何實(shí)現(xiàn)它們與其他數(shù)據(jù)類型的轉(zhuǎn)換?編譯器不知道怎樣實(shí)現(xiàn)用戶自定義類型與內(nèi)部數(shù)據(jù)類型之間的轉(zhuǎn)換。通常采用兩種方法:構(gòu)造函數(shù)實(shí)現(xiàn)類型轉(zhuǎn)換和用類類型轉(zhuǎn)換函數(shù)進(jìn)行類型轉(zhuǎn)換。

?

6.5.2用構(gòu)造函數(shù)實(shí)現(xiàn)類型轉(zhuǎn)換

用構(gòu)造函數(shù)完成類型轉(zhuǎn)換,類內(nèi)至少定義一個(gè)只帶一個(gè)參數(shù)的構(gòu)造函數(shù)。這樣,當(dāng)進(jìn)行類型轉(zhuǎn)換時(shí),系統(tǒng)會(huì)自動(dòng)調(diào)用該構(gòu)造函數(shù),創(chuàng)建該類的一個(gè)臨時(shí)對象,該對象由被轉(zhuǎn)換的值初始化,從而實(shí)現(xiàn)類型轉(zhuǎn)換。

將一個(gè)char型數(shù)據(jù)轉(zhuǎn)換為string類型數(shù)據(jù):

#include <iostream> #include <string.h> using namespace std; class String {private:char *str;int length;public:String(char *in_str);~String();void showstring(); };String::String(char *in_str) {length = strlen(in_str);str = new char[length+1];strcpy(str, in_str); }String::~String() {delete []str; }void String::showstring() {cout << str <<endl; }int main() {String s = (char*)"C/C++ Program";s.showstring();return 0; }

語句String(char *s);聲明了一個(gè)轉(zhuǎn)換構(gòu)造函數(shù)。該構(gòu)造函數(shù)可以用來進(jìn)行類型轉(zhuǎn)換。main函數(shù)中,在執(zhí)行語句String s = “C/C++ program”;時(shí),編譯系統(tǒng)首先調(diào)用構(gòu)造函數(shù)建立包含C/C++ program的一個(gè)臨時(shí)string對象,然后再將該臨時(shí)string對象賦給對象s。使用這種轉(zhuǎn)換構(gòu)造函數(shù)意味著不用再為將字符串賦給string類對象提供重載的賦值操作符(因?yàn)榛具\(yùn)算符”=”不允許將一個(gè)char*字符串賦給一個(gè)string類對象)。任何只帶一個(gè)參數(shù)(或其他參數(shù)都帶有默認(rèn)值)的構(gòu)造函數(shù)都可以認(rèn)為是一種轉(zhuǎn)換構(gòu)造函數(shù)。

?

預(yù)定義類型向自定義的類類型轉(zhuǎn)換:

#include <iostream> using namespace std;class Complex {private:double real,imag;public:Complex();Complex(int r);Complex(double r, double i);void Print();friend Complex operator+(Complex a, Complex b); };Complex::Complex() {real = imag = 0; }Complex::Complex(int r) {real = r;imag = 0; }Complex::Complex(double r, double i) {real = r;imag = i; }Complex operator+(Complex a, Complex b) {Complex temp;temp.real = a.real + b.real;temp.imag = a.imag + b.imag;return temp; }void Complex::Print() {cout <<real;if(imag > 0)cout << "+";if(imag != 0)cout << imag << "i" <<endl; }int main() {Complex com1(1.1, 2.2), com2, com3 = 10;cout << "com1:";com1.Print();com1 = 20 + com1;cout << "com1=20+com1:" <<endl;com1.Print();com2 = 10 + 200;cout << "com2=10+200:" <<endl;com2.Print();cout <<endl;cout << "com3=10:" <<endl;com3.Print();cout <<endl;return 0; }

譯程序在分析賦值表達(dá)式com3 = 10;時(shí),根據(jù)隱式類型轉(zhuǎn)換規(guī)則,將整數(shù)10轉(zhuǎn)換為com3的類型,通過調(diào)用構(gòu)造函數(shù)Complex(int r)完成所需要的類型轉(zhuǎn)換。在分析賦值表達(dá)式com1 = 20 + com1時(shí),編譯程序首先調(diào)用構(gòu)造函數(shù)Complex(int r)將整數(shù)20轉(zhuǎn)換成Complex類型,然后再調(diào)用運(yùn)算符函數(shù)operator+完成兩個(gè)Complex類型數(shù)據(jù)的加法運(yùn)算,最后再賦值。在賦值表達(dá)式com2 = 10 + 200時(shí),編譯系統(tǒng)首先完成整數(shù)的加法運(yùn)算,然后再調(diào)用構(gòu)造函數(shù)Complex(int r)將整型數(shù)210轉(zhuǎn)換成Complex類型,最后再賦值。

這寫這個(gè)代碼的時(shí)候還犯了一個(gè)小錯(cuò)誤(出現(xiàn)了重載構(gòu)造函數(shù)模糊的情況):

原因是我開始寫的兩個(gè)構(gòu)造函數(shù)是:

Complex(); Complex(double r = 0, double i = 0); //Complex(double r, double i); //解決問題

?

6.5.3用類類型轉(zhuǎn)換函數(shù)進(jìn)行類型轉(zhuǎn)換

使用構(gòu)造函數(shù)可以實(shí)現(xiàn)類型轉(zhuǎn)換,但是其所完成的類型轉(zhuǎn)換功能具有一定的局限性。由于無法為系統(tǒng)預(yù)定義類型定義構(gòu)造函數(shù),因此,不能利用構(gòu)造函數(shù)把自定義類型的數(shù)據(jù)轉(zhuǎn)換為系統(tǒng)預(yù)定義類型的數(shù)據(jù),只能實(shí)現(xiàn)系統(tǒng)預(yù)定義類型向自定義的類類型轉(zhuǎn)換。

為了解決上述問題,C++允許用戶在源類中定義類類型轉(zhuǎn)換函數(shù),從而實(shí)現(xiàn)吧源類類型轉(zhuǎn)換成目的類型。

類類型轉(zhuǎn)換函數(shù)定義格式:

class 源類類名 {//... operator 目的類型() {//...return 目的類型的數(shù)據(jù); } };

其中,源類類名為要轉(zhuǎn)換的源類類型;目的類型為要轉(zhuǎn)換成的類型,它既可以是用戶自定義的類型,也可以是系統(tǒng)的預(yù)定義類型。

使用類類型轉(zhuǎn)換函數(shù)時(shí),需要注意:

(1)類類型轉(zhuǎn)換函數(shù)只能定義為一個(gè)類的成員函數(shù),而不能定義為類的友元函數(shù)。

(2)類類型轉(zhuǎn)換函數(shù)既沒有參數(shù),也不顯式給出返回類型。

(3)類類型函數(shù)中必須有return目的類型的數(shù)據(jù);的語句,即必須返回目的類型數(shù)據(jù)作為函數(shù)的返回值。

自定義類型向預(yù)定義類型的轉(zhuǎn)換(顯式調(diào)用):

#include <iostream> using namespace std;class Complex {private:double real,imag;public:Complex(double r = 0, double i = 0);operator float();operator int();void Print(); };Complex::Complex(double r, double i) {real = r;imag = i;cout << "Constructing..." <<endl; }Complex::operator float() {cout << "Type changed to float" <<endl;return real; }Complex::operator int() {cout << "Type changed to int" <<endl;return int(real); }void Complex::Print() {cout << "(" <<real << "," << imag << ")" <<endl; }int main() {Complex a(1.1, 2.2);a.Print();cout << float(a)*0.5 <<endl;Complex b(4.7, 6);b.Print();cout << int(b)*2 <<endl;return 0; }

用隱式轉(zhuǎn)換實(shí)現(xiàn)類類型轉(zhuǎn)換:

#include <iostream> using namespace std;class Complex {private:double real,imag;public:Complex(double r, double i);Complex(double i = 0);operator double();void Print(); };Complex::Complex(double r, double i) {real = r;imag = i; }Complex::Complex(double i) {real = imag = i; }Complex::operator double() {cout << "Type changed to double" <<endl;return real+imag; }void Complex::Print() {cout << "(" <<real << "," << imag << ")" <<endl; }int main() {Complex a(1.1, 2.2), b(2.3, 3.2), c;c = a + b;c.Print(); return 0; }

本程序類Complex并沒有重載運(yùn)算符”+”,是如何實(shí)現(xiàn)”+”的運(yùn)算的?這是由于C++可以自動(dòng)進(jìn)行隱式轉(zhuǎn)換。在執(zhí)行語句com = com1 + com2;時(shí),首先尋找成員函數(shù)的+運(yùn)算符,沒有找到;尋找非成員函數(shù)的+運(yùn)算符,也沒有找到。由于系統(tǒng)中存在基本類型的+運(yùn)算,因此尋找能將參數(shù)轉(zhuǎn)換成基本類型的類型轉(zhuǎn)換函數(shù),結(jié)果找到operator double(),于是調(diào)用operator double()將com1和com2轉(zhuǎn)換成了double類型,然后進(jìn)行相加,由于最后要將結(jié)果賦給Complex類的對象,因此調(diào)用構(gòu)造函數(shù)Complex(double i)將相加所得的結(jié)果轉(zhuǎn)換成Complex類的一個(gè)臨時(shí)對象,然后將其賦給Complex對象com。

用類類型轉(zhuǎn)換函數(shù)實(shí)現(xiàn)復(fù)數(shù)類型向二維向量類型的轉(zhuǎn)換:

#include <iostream> using namespace std;class Vector {private:double x,y; public:Vector(double tx = 0, double ty = 0);void print(); };class Complex {private:double real,imag;public:Complex(double r = 0, double i = 0);operator Vector(); };Complex::Complex(double r, double i) {real = r;imag = i; }Complex::operator Vector() {return Vector(real, imag); }Vector::Vector(double tx, double ty) {x = tx;y = ty; }void Vector::print() {cout << "(" << x << "," << y << ")" <<endl; }int main() {Vector v;Complex a(1.1, 2.2);v = a;v.print();return 0; }

?

總結(jié)

以上是生活随笔為你收集整理的C++学习笔记:(四)运算符重载 类型转换的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

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