1. 程式人生 > >1.練習型別轉換函式

1.練習型別轉換函式

第一步分析:
Complex c1(1,2);
Complex c2;
c2 = c1 + 2;
當你寫好算術表示式之後,系統會自動判斷準備到底執行呼叫下面哪種operator+
一個是 自定義型別  Complex + Complex的 +運算子過載operator+ 
一個是 內建的基本型別  int + int 的  +運算子過載operator+

真理 ->>> 記住一定是先有呼叫,才會發生隱式轉換。

看是提供了 Complex + Complex的 +運算子過載operator+ 
還是提供了  int + int 的  +運算子過載operator+

如果存在Complex + Complex的 +運算子過載operator+。
那麼之後系統會判斷呼叫Complex+Complex的operator+的方案是否可以,也就是此時再判斷(實參到形參的)型別轉換是否能成功。(這句話印證了真理)
如果此時也提供了int->Complex的單參轉換構造,那麼系統會認為此路可行。
如果此時並沒有提供int->Complex的單參轉換構造,那麼系統會認為此路不通。則不會選擇執行這個。


如果存在內建int + int的 +運算子過載operator+。
那麼之後系統會判斷呼叫c1.operator+(Complex &)的方案是否可以,也就是此時再判斷(實參到形參的)型別轉換是否能成功。(這句話印證了超級對的真理)
如果此時也提供了Complex->int的operator int操作符型別轉換函式,那麼系統會認為此路可行。
如果此時並沒有提供Complex->int的operator int操作符型別轉換函式,那麼系統會認為此路不通。則不會選擇執行這個。

如果同時存在上面兩個。且上面兩個路都能通過
那麼系統就會報錯,歧義。系統不知道到底選哪個。
因為只有自定義型別與基本型別之間的運算才會容易鬧這個歧義的屁事。

第二步分析:
所以其實 只要寫上兩個型別轉換功能函式,     現在那麼就是已經在本類中支援了兩個方向轉,基本型別->本物件型別, 本物件型別->基本型別。。能不能實現順序不同的表示式的卡殼報錯地方並不在與,主要還是operator運算子過載函式的呼叫。在這方面理解必須要紮實到位。
單參轉換建構函式 可以通過int->Complex,只能來單獨實現c1+2表示式 ,不能單獨實現2+c1表示式,因為前提是呼叫了類內的Complex+Complex的operator+。如果想通過int->Complex,來單獨實現2+c1表示式 或 同時實現c1+2 和2+c1表示式。 那就把Complex+Complex的operator+,設為全域性函式,且設為Complex類的友元即可。

型別轉換操作符函式,可以通過Complex->int,來單獨實現c1+2。 前提是呼叫了全域性的內建+。
型別轉換操作符函式,既可以通過Complex->int 來同時實現c1+2表示式和2+c1表示式,即兩個表示式功能同時可存在。前提都是呼叫了全域性的內建+
 


第三步著手驗證:
————————————————————————————————————————————————————————

一.通過型別轉換同時實現下面兩行程式碼:
c2 = c1 + 5;    
c2 = 5 + c1;
1. int轉為Complex
#include <iostream>
using namespace std;
class Complex
{
    friend Complex operator+(const Complex & c1,const Complex & c2);
public:
    Complex()
    {
        cout<<"Complex()"<<endl;
        this->_x = 0;
        this->_y = 0;
    }
    Complex(int x,int y)
        :_x(x),_y(y)
    {
        cout<<"Complex(int x,int y)"<<endl;
    }
    Complex(const Complex& c2)
        :_x(c2._x),_y(c2._y)
    {
        cout<<"Complex(const Complex& c2)"<<endl;
    }
#if 1
    Complex operator+(const Complex & c2)
    {
       cout<<"Complex operator+(const Complex & c2)"<<endl;
       Complex temp(this->_x+c2._x,this->_y+c2._y);
       return temp;
    }
#endif

    Complex& operator=(const Complex & c2)
    {
        this->_x = c2._x;
        this->_y = c2._y;
        return *this;
    }
#if 1//int -> Complex
    Complex(int x)
        :_x(x),_y(0)
    {
        cout<<"Complex(int x)"<<endl;
    }
#endif
#if 0//Complex ->int
    operator int()
    {
        cout<<"operator int()"<<endl;
        return _x;
    }
#endif
private:
    int _x;
    int _y;
};

Complex operator+(const Complex & c1,const Complex & c2)
{
    cout<<"Complex operator+(const Complex & c2)"<<endl;
    Complex temp(c1._x+c2._x,c2._x+c2._y);
    return temp;
}

int main()
{
    Complex c1(1,2);
    Complex c2;
    c2 = c1 + 5;//->呼叫Complex::operator+(const Complex & c2) -> int轉為Complex
    c2 = 5 + c1;//->呼叫Complex operator+(const Complex & c1,const Complex & c2) -> int轉為Complex

    return 0;
}

2.Complex轉為int, 但是這樣子不好,因為必須不能自實現自定義的operator+,必須關閉此路。

#include <iostream>
using namespace std;
class Complex
{
public:
    Complex()
    {
        cout<<"Complex()"<<endl;
        this->_x = 0;
        this->_y = 0;
    }
    Complex(int x,int y)
        :_x(x),_y(y)
    {
        cout<<"Complex(int x,int y)"<<endl;
    }
    Complex(const Complex& c2)
        :_x(c2._x),_y(c2._y)
    {
        cout<<"Complex(const Complex& c2)"<<endl;
    }
#if 0 //關掉此路之後才對
    Complex operator+(const Complex & c2)
    {
       cout<<"Complex operator+(const Complex & c2)"<<endl;
       Complex temp(this->_x+c2._x,this->_y+c2._y);
       return temp;
    }
#endif

    Complex& operator=(const Complex & c2)
    {
        this->_x = c2._x;
        this->_y = c2._y;
        return *this;
    }
#if 1//int -> Complex
    Complex(int x)
        :_x(x),_y(0)
    {
        cout<<"Complex(int x)"<<endl;
    }
#endif
#if 1//Complex ->int
    operator int()
    {
        cout<<"operator int()"<<endl;
        return _x;
    }
#endif
private:
    int _x;
    int _y;
};

int main()
{
    Complex c1(1,2);
    Complex c2;
    c2 = c1 + 5;//->呼叫內建operator+(int ,int ) -> Complex轉為int
    c2 = 5 + c1;//->呼叫內建operator+(int ,int ) -> Complex轉為int
    return 0;
}

 

二.通過型別轉換同時實現下面兩行程式碼:
int value;
value = c1 + 5;
value = 5 + c1;

1..Complex轉為int

#include <iostream>
using namespace std;
class Complex
{
public:
    Complex()
    {
        cout<<"Complex()"<<endl;
        this->_x = 0;
        this->_y = 0;
    }
    Complex(int x,int y)
        :_x(x),_y(y)
    {
        cout<<"Complex(int x,int y)"<<endl;
    }
    Complex(const Complex& c2)
        :_x(c2._x),_y(c2._y)
    {
        cout<<"Complex(const Complex& c2)"<<endl;
    }
#if 1
    Complex operator+(const Complex & c2)
    {
       cout<<"Complex operator+(const Complex & c2)"<<endl;
       Complex temp(this->_x+c2._x,this->_y+c2._y);
       return temp;
    }
#endif
    Complex& operator=(const Complex & c2)
    {
        this->_x = c2._x;
        this->_y = c2._y;
        return *this;
    }
#if 0//int -> Complex
    Complex(int x)
        :_x(x),_y(0)
    {
        cout<<"Complex(int x)"<<endl;
    }
#endif
#if 1//Complex ->int
    operator int()
    {
        cout<<"operator int()"<<endl;
        return _x;
    }
#endif
private:
    int _x;
    int _y;
};

int main()
{
    Complex c1(1,2);
    int value;
    value = c1 + 5;//->呼叫內建operator+(int,int) -> Complex轉為int
    value = 5 + c1;//->呼叫內建operator+(int,int) -> Complex轉為int
    return 0;
}

2.int轉為Complex    無法實現同時共存兩個表示式,下面的程式碼編譯不通過。  原因在於無法關閉內建operator+(int,int )這條路。目前不知怎麼關閉。
 

//編譯不通過。
#include <iostream>
using namespace std;
class Complex
{
    friend Complex operator+(const Complex & c1,const Complex & c2);
public:
    Complex()
    {
        cout<<"Complex()"<<endl;
        this->_x = 0;
        this->_y = 0;
    }
    Complex(int x,int y)
        :_x(x),_y(y)
    {
        cout<<"Complex(int x,int y)"<<endl;
    }
    Complex(const Complex& c2)
        :_x(c2._x),_y(c2._y)
    {
        cout<<"Complex(const Complex& c2)"<<endl;
    }
#if 1
    Complex operator+(const Complex & c2)
    {
       cout<<"Complex operator+(const Complex & c2)"<<endl;
       Complex temp(this->_x+c2._x,this->_y+c2._y);
       return temp;
    }
#endif
    Complex& operator=(const Complex & c2)
    {
        this->_x = c2._x;
        this->_y = c2._y;
        return *this;
    }
#if 1//int -> Complex
    Complex(int x)
        :_x(x),_y(0)
    {
        cout<<"Complex(int x)"<<endl;
    }
#endif
#if 1//Complex ->int
    operator int()
    {
        cout<<"operator int()"<<endl;
        return _x;
    }
#endif
private:
    int _x;
    int _y;
};

Complex operator+(const Complex & c1,const Complex & c2)
{
    cout<<"Complex operator+(const Complex & c2)"<<endl;
    Complex temp(c1._x+c2._x,c2._x+c2._y);
    return temp;
}

int main()
{
    Complex c1(1,2);
    int value;
    value = c1 + 5;//->呼叫Complex::operator+(const Complex & c2) -> int轉為Complex    ->最後再轉為int 賦給左值
    value = 5 + c1;//->呼叫Complex operator+(const Complex & c1,const Complex & c2) -> int轉為Complex ->最後再轉為int 賦給左值
    return 0;
}

三.通過型別轉換同時實現下面兩行程式碼:
int value;
c2 = c1 + 5;
value = 5 + c1;

#include <iostream>
using namespace std;
class Complex
{
public:
    Complex()
    {
        cout<<"Complex()"<<endl;
        this->_x = 0;
        this->_y = 0;
    }
    Complex(int x,int y)
        :_x(x),_y(y)
    {
        cout<<"Complex(int x,int y)"<<endl;
    }
    Complex(const Complex& c2)
        :_x(c2._x),_y(c2._y)
    {
        cout<<"Complex(const Complex& c2)"<<endl;
    }
#if 0 //必須關掉此路
    Complex operator+(const Complex & c2)
    {
       cout<<"Complex operator+(const Complex & c2)"<<endl;
       Complex temp(this->_x+c2._x,this->_y+c2._y);
       return temp;
    }
#endif
    Complex& operator=(const Complex & c2)
    {
        this->_x = c2._x;
        this->_y = c2._y;
        return *this;
    }
#if 1//int -> Complex
    Complex(int x)
        :_x(x),_y(0)
    {
        cout<<"Complex(int x)"<<endl;
    }
#endif
#if 1//Complex ->int
    operator int()
    {
        cout<<"operator int()"<<endl;
        return _x;
    }
#endif
private:
    int _x;
    int _y;
};
int main()
{
    Complex c1(1,2);
    Complex c2;
    int value;
    //下面倆程式碼=右邊都是Complex轉為int ,然後第一個再轉為Complex. 
    c2 = c1 + 5;//必須關掉Complex operator+(const Complex & c2)此路,才能與下面表示式程式碼共存
    value = 5 + c1;
    return 0;
}


四。通過型別轉換同時實現下面兩行程式碼:
Complex c1(1,2);
Complex c2;
int value;
c2 = 5 + c1;
value = c1 + 5;
懶得去試寫了。感覺有點無意義。

 

關於實現型別轉換時謹記兩點:
//1.感覺最後還是加explict,來只允許強制才用的更舒服。所以還是別讓系統自動選路了,省的老引發歧義,導致各種不能同時實現的問題。
//2.切務必要遵循目的語義,不要像上面那些的試驗亂來。先確定語義再搞實現。確定想讓哪個轉哪個,而不是追求表示式程式碼共存(一效率低,二可能無意義)。