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

歡迎訪問 生活随笔!

生活随笔

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

c/c++

C++ 转换构造函数

發布時間:2025/3/12 c/c++ 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C++ 转换构造函数 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

在 C/C++ 中,不同的數據類型之間可以相互轉換。無需用戶指明如何轉換的稱為自動類型轉換(隱式類型轉換),需要用戶顯式地指明如何轉換的稱為強制類型轉換。

自動類型轉換示例:

int a = 6; a = 7.5 + a;

編譯器對 7.5 是作為 double 類型處理的,在求解表達式時,先將 a 轉換為 double 類型,然后與 7.5 相加,得到和為 13.5。在向整型變量 a 賦值時,將 13.5 轉換為整數 13,然后賦給 a。整個過程中,我們并沒有告訴編譯器如何去做,編譯器使用內置的規則完成數據類型的轉換。

強制類型轉換示例:

int n = 100; int *p1 = &n; float *p2 = (float*)p1;

p1 是int *類型,它指向的內存里面保存的是整數,p2 是float *類型,將 p1 賦值給 p2 后,p2 也指向了這塊內存,并把這塊內存中的數據作為小數處理。我們知道,整數和小數的存儲格式大相徑庭,將整數作為小數處理非常荒誕,可能會引發莫名其妙的錯誤,所以編譯器默認不允許將 p1 賦值給 p2。但是,使用強制類型轉換后,編譯器就認為我們知道這種風險的存在,并進行了適當的權衡,所以最終還是允許了這種行為。

不管是自動類型轉換還是強制類型轉換,前提必須是編譯器知道如何轉換,例如,將小數轉換為整數會抹掉小數點后面的數字,將int *轉換為float *只是簡單地復制指針的值,這些規則都是編譯器內置的,我們并沒有告訴編譯器。

換句話說,如果編譯器不知道轉換規則就不能轉換,使用強制類型也無用,請看下面的例子:

#include <iostream> using namespace std;//復數類 class Complex{ public:Complex(): m_real(0.0), m_imag(0.0){ }Complex(double real, double imag): m_real(real), m_imag(imag){ } public:friend ostream & operator<<(ostream &out, Complex &c); //友元函數 private:double m_real; //實部double m_imag; //虛部 };//重載>>運算符 ostream & operator<<(ostream &out, Complex &c){out << c.m_real <<" + "<< c.m_imag <<"i";;return out; }int main(){Complex a(10.0, 20.0);a = (Complex)25.5; //錯誤,轉換失敗return 0; }

25.5 是實數,a 是復數,將 25.5 賦值給 a 后,我們期望 a 的實部變為 25.5,而虛部為 0。但是,編譯器并不知道這個轉換規則,這超出了編譯器的處理能力,所以轉換失敗,即使加上強制類型轉換也無用。

C++ 允許我們自定義類型轉換規則,用戶可以將其它類型轉換為當前類類型,也可以將當前類類型轉換為其它類型。這種自定義的類型轉換規則只能以類的成員函數的形式出現,換句話說,這種轉換規則只適用于類。

轉換構造函數

將其它類型轉換為當前類類型需要借助轉換構造函數(Conversion constructor)。轉換構造函數也是一種構造函數,它遵循構造函數的一般規則。轉換構造函數只有一個參數。

以 Complex 類為例,我們為它添加轉換構造函數:

#include <iostream> using namespace std;//復數類 class Complex{ public:Complex(): m_real(0.0), m_imag(0.0){ }Complex(double real, double imag): m_real(real), m_imag(imag){ }Complex(double real): m_real(real), m_imag(0.0){ } //轉換構造函數 public:friend ostream & operator<<(ostream &out, Complex &c); //友元函數 private:double m_real; //實部double m_imag; //虛部 };//重載>>運算符 ostream & operator<<(ostream &out, Complex &c){out << c.m_real <<" + "<< c.m_imag <<"i";;return out; }int main(){Complex a(10.0, 20.0);cout<<a<<endl;a = 25.5; //調用轉換構造函數cout<<a<<endl;return 0; }

運行結果:

10 + 20i 25.5 + 0i

Complex(double real);就是轉換構造函數,它的作用是將 double 類型的參數 real 轉換成 Complex 類的對象,并將 real 作為復數的實部,將 0 作為復數的虛部。這樣一來,a = 25.5;整體上的效果相當于:

a.Complex(25.5);

將賦值的過程轉換成了函數調用的過程。

在進行數學運算、賦值、拷貝等操作時,如果遇到類型不兼容、需要將 double 類型轉換為 Complex 類型時,編譯器會檢索當前的類是否定義了轉換構造函數,如果沒有定義的話就轉換失敗,如果定義了的話就調用轉換構造函數。

轉換構造函數也是構造函數的一種,它除了可以用來將其它類型轉換為當前類類型,還可以用來初始化對象,這是構造函數本來的意義。下面創建對象的方式是正確的:

Complex c1(26.4); //創建具名對象 Complex c2 = 240.3; //以拷貝的方式初始化對象 Complex(15.9); //創建匿名對象 c1 = Complex(46.9); //創建一個匿名對象并將它賦值給 c1

在以拷貝的方式初始化對象時,編譯器先調用轉換構造函數,將 240.3 轉換為 Complex 類型(創建一個 Complex 類的匿名對象),然后再拷貝給 c2。

如果已經對+運算符進行了重載,使之能進行兩個 Complex 類對象的相加,那么下面的語句也是正確的:

Complex c1(15.6, 89.9); Complex c2; c2 = c1 + 29.6; cout<<c2<<endl;

在進行加法運算符時,編譯器先將 29.6 轉換為 Complex 類型(創建一個 Complex 類的匿名對象)再相加。

注意:為了獲得目標類型,編譯器會“不擇手段”,會綜合使用內置的轉換規則和用戶自定義的轉換規則,并且會進行多級類型轉換,例如:
編譯器會根據內置規則先將 int 轉換為 double,再根據用戶自定義規則將 double 轉換為 Complex(int --> double --> Complex);

編譯器會根據內置規則先將 char 轉換為 int,再將 int 轉換為 double,最后根據用戶自定義規則將 double 轉換為 Complex(char --> int --> double --> Complex)。

從本例看,只要一個類型能轉換為 double 類型,就能轉換為 Complex 類型。請看下面的例子:

int main(){Complex c1 = 100; //int --> double --> Complexcout<<c1<<endl;c1 = 'A'; //char --> int --> double --> Complexcout<<c1<<endl;c1 = true; //bool --> int --> double --> Complexcout<<c1<<endl;Complex c2(25.8, 0.7);//假設已經重載了+運算符c1 = c2 + 'H' + true + 15; //將char、boolint都轉換為Complex類型再運算cout<<c1<<endl;return 0; }

運行結果:

100 + 0i 65 + 0i 1 + 0i 113.8 + 0.7i

構造函數

構造函數的本意是在創建對象的時候初始化對象,編譯器會根據傳遞的實參來匹配不同的(重載的)構造函數

1 默認構造函數。就是編譯器自動生成的構造函數。以 Complex 類為例,它的原型為:

Complex(); //沒有參數

2 普通構造函數。就是用戶自定義的構造函數。以 Complex 類為例,它的原型為:

Complex(double real, double imag); //兩個參數

3 拷貝構造函數。在以拷貝的方式初始化對象時調用。以 Complex 類為例,它的原型為:

Complex(const Complex &c);

4 轉換構造函數。將其它類型轉換為當前類類型時調用。以 Complex 為例,它的原型為:

Complex(double real);

不管哪一種構造函數,都能夠用來初始化對象,這是構造函數的本意。假設 Complex 類定義了以上所有的構造函數,那么下面創建對象的方式都是正確的:

Complex c1(); //調用Complex() Complex c2(10, 20); //調用Complex(double real, double imag) Complex c3(c2); //調用Complex(const Complex &c) Complex c4(25.7); //調用Complex(double real)

這些代碼都體現了構造函數的本意——在創建對象時初始化對象。

除了在創建對象時初始化對象,其他情況下也會調用構造函數,例如,以拷貝的的方式初始化對象時會調用拷貝構造函數,將其它類型轉換為當前類類型時會調用轉換構造函數。這些在其他情況下調用的構造函數,就成了特殊的構造函數了。特殊的構造函數并不一定能體現出構造函數的本意。

Complex 類的精簡

上面的 Complex 類中我們定義了三個構造函數,其中包括兩個普通的構造函數和一個轉換構造函數。其實,借助函數的默認參數,我們可以將這三個構造函數簡化為一個,請看下面的代碼:

#include <iostream> using namespace std;//復數類 class Complex{ public:Complex(double real = 0.0, double imag = 0.0): m_real(real), m_imag(imag){ } public:friend ostream & operator<<(ostream &out, Complex &c); //友元函數 private:double m_real; //實部double m_imag; //虛部 };//重載>>運算符 ostream & operator<<(ostream &out, Complex &c){out << c.m_real <<" + "<< c.m_imag <<"i";;return out; }int main(){Complex a(10.0, 20.0); //向構造函數傳遞 2 個實參,不使用默認參數Complex b(89.5); //向構造函數傳遞 1 個實參,使用 1 個默認參數Complex c; //不向構造函數傳遞實參,使用全部默認參數a = 25.5; //調用轉換構造函數(向構造函數傳遞 1 個實參,使用 1 個默認參數)return 0;}

精簡后的構造函數包含了兩個默認參數,在調用它時可以省略部分或者全部實參,也就是可以向它傳遞 0 個、1 個、2 個實參。轉換構造函數就是包含了一個參數的構造函數,恰好能夠和其他兩個普通的構造函數“融合”在一起。

總結

以上是生活随笔為你收集整理的C++ 转换构造函数的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。