天天看點

無名對象簡化運算符重載函數

http://www.pconline.com.cn/pcedu/empolder/gj/c/0503/584861.html

在完整描述思想之前,我們先看一下如下的例子,這個例子中的加運算符重載是以非成員函數的方式出現的:

#include <iostream>  
using namespace std;  
class Test{    
    public:    
        Test(int a){  
            Test::a = a;  
        }  
        friend Test operator + (Test&,int);  
    public:  
        int a;  
};  
Test operator + (Test &temp1,int temp2){  
    Test result(temp1.a + temp2);  
    return result;  
}  
int main(){  
    Test a(100);  
    a = a + 10;//正确  
    a = 10 + a;//錯誤  
    cout<<a.a<<endl;  
    system("pause");  
}
           

  上面的代碼是一個自定義類對象與内置整型對象相加的例子,但錯誤行讓我們猛然感覺很詫異,但仔細看看的确也在情理中,參數順序改變後c++無法識别可供使用的運算符重載函數了。

  我們為了适應順序問題不得不多加一個幾乎一樣的運算符重載函數。

  代碼如下:

#include <iostream>  
using namespace std;  
class Test{    
    public:    
        Test(int a){  
            Test::a = a;  
        }  
        friend Test operator + (Test&,int);  
        friend inline Test operator + (Test&,int);  
    public:  
        int a;  
};  
Test operator + (Test &temp1,int temp2){  
    Test result(temp1.a + temp2);  
    return result;  
}  
inline Test operator + (int temp1,Test &temp2)//利用内聯函數的定義提高效率  
{    return temp2+temp1;  
}  
int main(){  
    Test a(100);  
    a = a + 10;//正确  
    a = 10 + a;//正确  
    cout<<a.a<<endl;  
    system("pause");  
}
           

  代碼中我們使用内聯函數的目的是為了縮減開銷,但事實上我們仍然覺得是比較麻煩的,例子中的情況都還是非成員函數的情況,如果運算符重載函數是作為類成員函數,那麼問題就來了,重載函數的第一個參數始終被隐藏,我們無發讓int形參排列在隐藏參數的前面,進而導緻a = 10 + a;無法擷取正确的運算符重載函數

     有問題的代碼如下:

class Test{    
    public:    
        Test(int a){  
            Test::a = a;  
        }  
        Test operator + (int temp2){  
                Test result(temp1.a + temp2);  
                return result;  
        }  
        Test operator + ()//第一個參數被隐藏,怎麼辦????,int形參無法放到this指針的前面,理想中的應該是(int temp1,Test *this)  
        {    
        }  
    public:  
        int a;    
};
           

  對于這個問題難道沒有辦法解決嗎? 

  答案是否定的, 我們可以利用類構造函數對參與運算的整型對象進行顯式的類型轉換,進而生成無名對象參與同類型對象的加運算 ,這樣做可以縮減代碼量,提高程式的可讀性。 

  代碼如下(例一為非成員形式,例二為成員形式):

#include <iostream>  
using namespace std;  
class Test {    
    public:    
        Test(int a)//事實上構造函數起的轉換作用本質就是産生無名對象  
        {Test::a = a;  
        }  
    friend Test operator + (Test&,Test&);  
    public:  
    int a;  
};  
Test operator + (Test &temp1,Test &temp2){  
    Test result(temp1.a + temp2.a);  
    return result;  
}  
int main(){  
    Test a(100);  
    a = a + Test(10);//顯式轉換,産生無名對象  
    a = Test(10) + a;  
    cout<<a.a<<endl;  
    a = 50 + 1;//先進行50+1的内置整型的加運算,然後進行a=Test(51)的隐式轉換  
    cout<<a.a<<endl;  
    system("pause");  
}
           
#include <iostream>  
using namespace std;  
class Test{    
    public:    
        Test(int a)//事實上構造函數起的轉換作用本質就是産生無名對象  
        {       Test::a = a;  
        }  
        Test operator + (Test &temp)//第一個參數即使隐藏也沒有關系,因為是以Test類型的無名對象參與運算的  
        {       Test result(this->a + temp.a);  
                return result;  
        }  
    public:  
        int a;  
};  
int main(){  
    Test a(100);  
    a = a + Test(10);  
    a = Test(10) + a;  
    cout<<a.a<<endl;  
    a = 50 + 1;//先進行50+1的内置整型的加運算,然後進行a=Test(51)的隐式轉換  
    cout<<a.a<<endl;  
    system("pause");  
}
           

  認真觀察了上面的兩個例子後我們可以發現,類的構造函數起了顯式或者隐式轉換的作用,轉換過程實質是産生一個類的無名對象,類的運算符重載函數的參數就是這個無名對象的引用,是以參數的順序也不再是問題,代碼的運作效率也得到提高,無需再定義隻是參數順序不同,内容重複的運算符重載函數了。