中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

C++中如何實現運算符重載

發布時間:2022-01-21 09:13:23 來源:億速云 閱讀:173 作者:小新 欄目:開發技術

這篇文章主要為大家展示了“C++中如何實現運算符重載”,內容簡而易懂,條理清晰,希望能夠幫助大家解決疑惑,下面讓小編帶領大家一起研究并學習一下“C++中如何實現運算符重載”這篇文章吧。

1、引例

class Complex
{
private:
    double Real,Image;
public:
    Complex():Real(0),Image(0)  {}
    Complex(double r, double i) : Real(r),Image(i) {}
    ~Complex()  {}
};

int main()
{
    Complex c1(1.2,2.3);
    Complex c2(45,56);

    Complex c3;
    c3 = c1.Add(c2);        
   
}

類非常簡單,下面我們要討論如何寫一個Add函數,使得兩個對象的屬性相加,返回一個新的對象。

第一種:

Complex::Complex Add(const Complex &c)
{
    Complex co;
    co.Real = this->Real + c.Real;
    co.Image = this->Image + c.Image;
    return co;
}

問題1:如何寫出最節省空間的Add函數?

第二種:

Complex::Complex Add(const Complex &c) const	
{
    return Complex(c.Real + this->Real, c.Image + this.Image);
}

由于不需要改變調用對象的屬性值,我們給this指針添加const 修飾。

分析過程如下:

C++中如何實現運算符重載

問題2:為什么第一種方式不節省空間呢?

首先第一種的代碼比較繁瑣,并且在函數棧幀中又創建了一個對象(第3行)。并且函數類型是值傳遞類型(第6行),返回的是一個將亡值對象。那么整個Add函數空間會產生兩個對象,造成空間的浪費。

第二中代碼創建的是無名對象,減少了一個co對象的創建,并且將無名對象直接作為將亡值對象傳遞給main函數中的c3。

問題3:我們能否將Add函數改為引用類型,這樣來減少將亡值對象的創建

Complex::Complex &Add(const Complex &c) const	
{
    return Complex(c.Real + this->Real, c.Image + this.Image);
}

VS2019發現報錯,不能返回引用對象:

C++中如何實現運算符重載

我們進行分析:

C++中如何實現運算符重載

問題4:我們能否將這個Add函數名改為 + 運算符?

//Complex::Complex Add(const Complex &c) const
Complex::Complex +(const Complex &c) const 
{
	Complex co;
	co.Real = this->Real + c.Real;
	co.Image = this->Image + c.Image;
	return co;
}

int main()
{
    ...
    //c3 = c1.Add(c2);  
    c3 = c1.+(c2);    //將原先Add的地方改變為加號。
    ...
}	

這樣使用,編譯器又會報錯,操作符不可作為一個有效的函數名來被使用

問題5:如何使 +預算符 作為函數名使用?

這就引出了今天的關鍵,函數運算符重載

在C++中,為了使操作符作為一個有效的函數名,我們在操作符前面添加一個operator

Complex operator+(const Complex &c) const 
{
     return Complex(c.Real + this->Real,c.Image + this->Image);
}

int main()
{
     Complex c1(1.2,2.3);
     Complex c2(10,10);
     Complex c3;
     c3 = c1 + c2;
    
     //上面一行實際上是
     //c3 = c1.operator+ (c2);
     //c3 = operator+(&c1,c2);  //編譯器還會經過一次編譯
}

前面幾篇博客已經分析了第15行的由來,是將c1的地址傳遞給this指針,將c2作為形參c的別名傳遞給函數。

2、類中自動建立的函數

在C++中,如果我們定義一個類,它會給我們自動創建六個缺省函數

構造函數析構函數拷貝構造函數賦值函數普通對象的&(取地址符)的重載常對象的&(取地址符)重載

代碼示例如下:

class Object
{
public:
    Object()    {}							//構造函數
    ~Object()   {}							//析構函數
    Object(const Object &obj)   {}			//拷貝構造函數
    Object &operator=() {const Object &obj} //賦值函數
    {
        return *this;
    }
    
    Object *operator&()						//普通對象的&(取地址符)的重載
    {
        return this;
    }
    
    const Object *operator&() const			//常對象的&(取地址符)重載
    {
        return this;
    }

};

然后,在C11標準下,又增添了兩個缺省函數,這里不做深究:

移動構造函數移動賦值函數

3、重載賦值運算符解析

回到最初的例子:

class Object
{
    int value;
public:
    Object ()   {
        cout << "create:" << this << endl;
    }                  //普通構造函數
    Object (int x = 0):value(x) {cout << "create:" << this << endl;}  //缺省構造函數
    ~Object()                       //析構函數
    {
        cout << "~Objcet() " << this << endl;
    }
    Object(Object &obj):value(obj.value)             
    {
        cout << "Copy create:" << this << endl;
    }

    int & Value()
    {
        return value;
    }

    const int &Value() const 
    {
        return value;
    }  
       
     Object &operator=(const Object& obj)        //此處加引用
    {
        this->value = obj.value;
        return *this;       //this指針指向objb的地址。賦值函數結束后,objb不會被消亡,所以可以以引用返回
    }
    
	void operator=(const Object& obj)       //賦值語句不可給this指針加const
    {
        this->value = obj.value;
    }
    
};

int main()
{
    Object objx(0);
    Object objy(0);
    objy = fun(objx);
    cout << objy.Value() << endl;
    return 0;
}

我們在34行添加一個等號運算符重載函數: void operator=(const Object& obj)

此處不可添加const修飾this指針,因為需要使用this指針作為左值被修改。

問題6:void operator=(const Object& obj) 只能用于 obja = objb,為什么不可以這樣使用 obja = objb = objc;

我們逐一分析:

obja = objb = objc;

//當調用等號運算符函數的時候。
obja = objb.operator = (objc);
obja = operator = (&objb,objc);
//如果此處是調用的是 void operator=(const Object& obj) ;
//等號從右向左指向,我們不能把一個void 類型賦給一個obja對象類型。

我們將賦值運算符進行再次重載,丟棄 void 版本:

Object &operator=(const Object& obj)        //此處加引用
{
	this->value = obj.value;
	return *this;       //this指針指向objb的地址。賦值函數結束后,objb不會被消亡,所以可以以引用返回
}

這樣就可以使用了。

我們接著上次的深入分析:

obja.operator=(operator=(&objb,objc));
operator=(&obja,operator=(&objb,objc));

問題7:如果遇到obja = obja這種情況,如何賦值呢?

回答:對this指針和形參引用進行判斷。

Object &operator=(const Object &obj)
{
    if(this != &obj)
    {
        this->value = obj.value
    }
}

問題8:為什么函數是在棧區構建的,以引用返回打印的不是一個隨機值?

運行程序,VS2012中,打印的是一個隨機值。

VS2019打印的是一個正常值。

c));

> 問題7:如果遇到obja = obja這種情況,如何賦值呢?
>
> 回答:對this指針和形參引用進行判斷。

```cpp
Object &operator=(const Object &obj)
{
    if(this != &obj)
    {
        this->value = obj.value
    }
}

問題8:為什么函數是在棧區構建的,以引用返回打印的不是一個隨機值?

運行程序,VS2012中,打印的是一個隨機值。

VS2019打印的是一個正常值。

在WIN10系統中,VS2019與操作系統完全結合,安全性更高。當程序多次運行的時候,它的邏輯地址都不一樣,這樣做的好處是:當病毒入侵時,由于程序的邏輯地址是變化的,病毒不好尋找入侵的入口。

以上是“C++中如何實現運算符重載”這篇文章的所有內容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內容對大家有所幫助,如果還想學習更多知識,歡迎關注億速云行業資訊頻道!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

c++
AI

岚皋县| 景德镇市| 罗平县| 陆河县| 商都县| 抚远县| 淮阳县| 阳西县| 临泉县| 敦化市| 齐河县| 通河县| 平凉市| 唐河县| 兰西县| 松潘县| 乳山市| 阜新| 阳新县| 安远县| 寻甸| 邵阳市| 从江县| 东丰县| 中方县| 安宁市| 碌曲县| 左权县| 高邮市| 大余县| 晋江市| 灵山县| 资阳市| 靖边县| 汉川市| 枣庄市| 张北县| 中山市| 溧阳市| 武功县| 云梦县|