C++中轉(zhuǎn)換構(gòu)造函數(shù):將其它類(lèi)型轉(zhuǎn)換為當(dāng)前類(lèi)的類(lèi)型

技術(shù)交流QQ群:1027579432,歡迎你的加入!

1.C++轉(zhuǎn)換構(gòu)造函數(shù):將其它類(lèi)型轉(zhuǎn)換為當(dāng)前類(lèi)的類(lèi)型

  • 在C/C++中,不同的數(shù)據(jù)類(lèi)型之間可以相互轉(zhuǎn)換。無(wú)需用戶(hù)指明如何轉(zhuǎn)換的稱(chēng)為自動(dòng)類(lèi)型轉(zhuǎn)換(隱式類(lèi)型轉(zhuǎn)換),需要用戶(hù)顯式地指明如何轉(zhuǎn)換的稱(chēng)為強(qiáng)制類(lèi)型轉(zhuǎn)換。
        // 自動(dòng)類(lèi)型轉(zhuǎn)換示例
        int a = 6;
        a = a + 3.12;  // 將小數(shù)轉(zhuǎn)換為整數(shù)會(huì)抹掉小數(shù)點(diǎn)后面的數(shù)字
        // 強(qiáng)制類(lèi)型轉(zhuǎn)換示例
        int b = 100;
        int *p = &b;
        float *ptr = (float *)p;  // 將int *轉(zhuǎn)換為float *只是簡(jiǎn)單地復(fù)制指針的值
    
  • 不管是自動(dòng)類(lèi)型轉(zhuǎn)換還是強(qiáng)制類(lèi)型轉(zhuǎn)換,前提必須是編譯器知道如何轉(zhuǎn)換,例如,將小數(shù)轉(zhuǎn)換為整數(shù)會(huì)抹掉小數(shù)點(diǎn)后面的數(shù)字,將int *轉(zhuǎn)換為float *只是簡(jiǎn)單地復(fù)制指針的值,這些規(guī)則都是編譯器內(nèi)置的,我們并沒(méi)有告訴編譯器??傊?,如果編譯器不知道轉(zhuǎn)換規(guī)則就不能轉(zhuǎn)換,使用強(qiáng)制類(lèi)型也無(wú)用,請(qǐng)看下面的例子:
        #include "iostream"
    
        using namespace std;
    
        // 如果編譯器不知道轉(zhuǎn)換規(guī)則就不能轉(zhuǎn)換,使用強(qiáng)制類(lèi)型也無(wú)用
        class complex{
            public:
                complex():m_real(0.0), m_img(0.0){}
                complex(double real, double img):m_real(real), m_img(img){}
            public:
                friend ostream & operator<< (ostream &out, const complex &c); // 友元函數(shù)
            private:
                double m_real;
                double m_img;
        };
    
        ostream & operator << (ostream &out, const complex &c){
            out << c.m_real << "+" << c.m_img << "i";
            return out;
        }
    
        int main(){
            complex a(10.0, 20.0);
            a = (complex) 25.5;  // 錯(cuò)誤,轉(zhuǎn)換失敗
            return 0;
        }
    
  • 上面的例子中,25.5是實(shí)數(shù),a是復(fù)數(shù),將25.5賦值給a后,我們期望a的實(shí)部變?yōu)?5.5,而虛部為0。但是,編譯器并不知道這個(gè)轉(zhuǎn)換規(guī)則,這超出了編譯器的處理能力,所以轉(zhuǎn)換失敗,即使加上強(qiáng)制類(lèi)型轉(zhuǎn)換也無(wú)用。幸運(yùn)的是,C++允許我們自定義類(lèi)型轉(zhuǎn)換規(guī)則,用戶(hù)可以將其它類(lèi)型轉(zhuǎn)換為當(dāng)前類(lèi)類(lèi)型,也可以將當(dāng)前類(lèi)類(lèi)型轉(zhuǎn)換為其它類(lèi)型。這種自定義的類(lèi)型轉(zhuǎn)換規(guī)則只能以類(lèi)的成員函數(shù)的形式出現(xiàn)。換句話說(shuō),這種轉(zhuǎn)換規(guī)則只適用于類(lèi),本節(jié)先講解如何將其它類(lèi)型轉(zhuǎn)換為當(dāng)前類(lèi)類(lèi)型。

2.轉(zhuǎn)換構(gòu)造函數(shù)

  • 將其它類(lèi)型轉(zhuǎn)換為當(dāng)前類(lèi)類(lèi)型需要借助轉(zhuǎn)換構(gòu)造函數(shù)(Conversion constructor)。轉(zhuǎn)換構(gòu)造函數(shù)也是一種構(gòu)造函數(shù),它遵循構(gòu)造函數(shù)的一般規(guī)則,轉(zhuǎn)換構(gòu)造函數(shù)只有一個(gè)參數(shù)
        #include "iostream"
    
        using namespace std;
    
        /*---------------------------將其它類(lèi)型轉(zhuǎn)換為當(dāng)前類(lèi)的類(lèi)型-------------------------------*/
    
        // 如果編譯器不知道轉(zhuǎn)換規(guī)則就不能轉(zhuǎn)換,使用強(qiáng)制類(lèi)型也無(wú)用
        class complex{
            public:
                complex():m_real(0.0), m_img(0.0){}
                complex(double real, double img):m_real(real), m_img(img){}
                complex(double real): m_real(real), m_img(0.0){}  // 轉(zhuǎn)換構(gòu)造函數(shù),作用是將double類(lèi)型的參數(shù)real轉(zhuǎn)換成 complex類(lèi)的對(duì)象,并將real作為復(fù)數(shù)的實(shí)部,將0作為復(fù)數(shù)的虛部
            public:
                friend ostream & operator<< (ostream &out, const complex &c); // 友元函數(shù)
            private:
                double m_real;
                double m_img;
        };
    
        ostream & operator << (ostream &out, const complex &c){
            out << c.m_real << " + " << c.m_img << "i";
            return out;
        }
    
        int main(){
            complex a(10.0, 20.0);
            cout << "a = " << a << endl;
            a = 25.5;  // 將賦值的過(guò)程轉(zhuǎn)換成了函數(shù)調(diào)用的過(guò)程
            cout << "a = " << a << endl;
            return 0;
        }
    
  • 轉(zhuǎn)換構(gòu)造函數(shù)也是構(gòu)造函數(shù)的一種,它除了可以用來(lái)將其它類(lèi)型轉(zhuǎn)換為當(dāng)前類(lèi)類(lèi)型,還可以用來(lái)初始化對(duì)象,這是構(gòu)造函數(shù)本來(lái)的意義。下面創(chuàng)建對(duì)象的方式是正確的:
        complex c1(23.1);  // 創(chuàng)建具名對(duì)象
        complex c2 = 24.3;  // 以拷貝的方式初始化對(duì)象,編譯器先調(diào)用轉(zhuǎn)換構(gòu)造函數(shù),將24.3轉(zhuǎn)換為complex類(lèi)型(創(chuàng)建一個(gè)complex類(lèi)的匿名對(duì)象),然后再拷貝給c2。
        complex(3.21);  // 創(chuàng)建匿名對(duì)象
        c1 = complex(34.2);  // 創(chuàng)建一個(gè)匿名對(duì)象并將它賦值給 c1
    
  • 如果已經(jīng)對(duì)+運(yùn)算符進(jìn)行了重載,使之能進(jìn)行兩個(gè)complex類(lèi)對(duì)象的相加,那么下面的語(yǔ)句也是正確的:
        complex c1(15.6, 89.9);
        complex c2;
        c2 = c1 + 29.6;
        cout << c2 << endl;
    
  • 注意:為了獲得目標(biāo)類(lèi)型,編譯器會(huì)“不擇手段”,會(huì)綜合使用內(nèi)置的轉(zhuǎn)換規(guī)則和用戶(hù)自定義的轉(zhuǎn)換規(guī)則,并且會(huì)進(jìn)行多級(jí)類(lèi)型轉(zhuǎn)換,例如:
    • 編譯器會(huì)根據(jù)內(nèi)置規(guī)則先將int轉(zhuǎn)換為double,再根據(jù)用戶(hù)自定義規(guī)則將double轉(zhuǎn)換為complex(int --> double --> complex);
    • 編譯器會(huì)根據(jù)內(nèi)置規(guī)則先將char轉(zhuǎn)換為int,再將int轉(zhuǎn)換為double,最后根據(jù)用戶(hù)自定義規(guī)則將double轉(zhuǎn)換為complex(char --> int --> double --> complex)
          int main(){
              complex c1 = 100;  //int --> double --> complex
              cout << c1 << endl;
              c1 = 'A';  //char --> int --> double --> complex
              cout << c1 << endl;
              c1 = true;  //bool --> int --> double --> complex
              cout << c1 << endl;
              complex c2(25.8, 0.7);
              //假設(shè)已經(jīng)重載了+運(yùn)算符
              c1 = c2 + 'H' + true + 15;  //將char、bool、int都轉(zhuǎn)換為complex類(lèi)型再運(yùn)算
              cout << c1 << endl;
              return 0;
          }
      

3.再談構(gòu)造函數(shù)

  • 構(gòu)造函數(shù)的本意是在創(chuàng)建對(duì)象的時(shí)候初始化對(duì)象,編譯器會(huì)根據(jù)傳遞的實(shí)參來(lái)匹配不同的(重載的)構(gòu)造函數(shù),幾種形式的構(gòu)造函數(shù):
    • 默認(rèn)構(gòu)造函數(shù): 就是編譯器自動(dòng)生成的構(gòu)造函數(shù),以complex類(lèi)為例,它的原型為:
          complex();  // 沒(méi)參數(shù)
      
    • 普通構(gòu)造函數(shù): 就是用戶(hù)自定義的構(gòu)造函數(shù),以complex類(lèi)為例,它的原型為:
          complex(double real, double img);  // 兩個(gè)參數(shù)
      
    • 拷貝構(gòu)造函數(shù): 在以拷貝的方式初始化對(duì)象時(shí)調(diào)用,以complex類(lèi)為例,它的原型為:
          complex(const complex &c);
      
    • 轉(zhuǎn)換構(gòu)造函數(shù): 將其它類(lèi)型轉(zhuǎn)換為當(dāng)前類(lèi)類(lèi)型時(shí)調(diào)用,以complex為例,它的原型為:
          complex(double real);  // 一個(gè)參數(shù)
      
  • 不管哪一種構(gòu)造函數(shù),都能夠用來(lái)初始化對(duì)象,這是構(gòu)造函數(shù)的本意。假設(shè)complex類(lèi)定義了以上所有的構(gòu)造函數(shù),那么下面創(chuàng)建對(duì)象的方式都是正確的:
        complex c1();  // 調(diào)用complex()
        complex c2(10, 20);  // 調(diào)用complex(double real, double imag)
        complex c3(c2);  // 調(diào)用complex(const complex &c)
        complex c4(25.7);  // 調(diào)用complex(double real)
    
  • 除了在創(chuàng)建對(duì)象時(shí)初始化對(duì)象,其他情況下也會(huì)調(diào)用構(gòu)造函數(shù),例如:以拷貝的的方式初始化對(duì)象時(shí)會(huì)調(diào)用拷貝構(gòu)造函數(shù),將其它類(lèi)型轉(zhuǎn)換為當(dāng)前類(lèi)類(lèi)型時(shí)會(huì)調(diào)用轉(zhuǎn)換構(gòu)造函數(shù)。這些在其他情況下調(diào)用的構(gòu)造函數(shù),就成了特殊的構(gòu)造函數(shù)了。特殊的構(gòu)造函數(shù)并不一定能體現(xiàn)出構(gòu)造函數(shù)的本意。

4.對(duì)complex類(lèi)的進(jìn)一步精簡(jiǎn)

  • 上面的complex類(lèi)中我們定義了三個(gè)構(gòu)造函數(shù),其中包括兩個(gè)普通的構(gòu)造函數(shù)和一個(gè)轉(zhuǎn)換構(gòu)造函數(shù)。其實(shí),借助函數(shù)的默認(rèn)參數(shù),我們可以將這三個(gè)構(gòu)造函數(shù)簡(jiǎn)化為一個(gè),請(qǐng)看下面的代碼:
        #include "iostream"
    
        using namespace std;
    
        /*---------------------------將其它類(lèi)型轉(zhuǎn)換為當(dāng)前類(lèi)的類(lèi)型-------------------------------*/
    
        // 如果編譯器不知道轉(zhuǎn)換規(guī)則就不能轉(zhuǎn)換,使用強(qiáng)制類(lèi)型也無(wú)用
        class complex{
            public:
                complex(double real=0.0, double img=0.0):m_real(real), m_img(img){}
            public:
                friend ostream & operator<< (ostream &out, const complex &c); // 友元函數(shù)
            private:
                double m_real;
                double m_img;
        };
    
        ostream & operator << (ostream &out, const complex &c){
            out << c.m_real << " + " << c.m_img << "i";
            return out;
        }
    
        int main(){
            complex a(10.0, 20.0);  // 向構(gòu)造函數(shù)傳遞2個(gè)實(shí)參,不使用默認(rèn)參數(shù)
            cout << "a = " << a << endl;
            complex b(89.5);  // 向構(gòu)造函數(shù)傳遞1個(gè)實(shí)參,使用1個(gè)默認(rèn)參數(shù)
            cout << "b = " << b << endl;
            complex c;  // 不向構(gòu)造函數(shù)傳遞實(shí)參,使用全部默認(rèn)參數(shù)
            a = 25.5;  // 調(diào)用轉(zhuǎn)換構(gòu)造函數(shù)(向構(gòu)造函數(shù)傳遞1個(gè)實(shí)參,使用1個(gè)默認(rèn)參數(shù))
            cout << "a = " << a << endl;
            return 0;
        }
    
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容