日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學無先后,達者為師

網站首頁 編程語言 正文

詳解C++中賦值,關系,函數調用運算符重載的實現_C 語言

作者:葉落秋白 ? 更新時間: 2022-08-04 編程語言

賦值運算符重載

在C++中基本數據類型例如整型,可以實現連續賦值:a=b=c;而我們的對象的成員屬性雖然可以相等,但是如果牽扯到堆地址,就會有深淺拷貝的問題存在。所以我們自己重載賦值運算符,實現連等的方法。

類結構

class Info
{
    int* m_a;
public:
    Info()
    {
        m_a = NULL;
    }
    Info(int a)
    {
        m_a = new int(a);
    }
    ~Info()
    {
        if (m_a != NULL)
            delete m_a;
        m_a = NULL;
    }
    
};

創建一個Info類,定義指針屬性*m_a, 然后自己定義Info類的無參、有參構造函數和析構函數,再給屬性賦值的時候,是用new關鍵字開辟堆區并存放數據;析構在前面的文章中講到了他的作用,就是在程序結束前編譯器自動調用析構來完成對象的清理工作,在這里就會把堆區的數據釋放掉。

問題的出現

Info f(20);
Info f1;
Info f2;
Info f3(30);
f1 = f2 =f;

直接連等是不行的,因為在析構函數里訪問了一個NULL地址,就比如程序即將結束,f調用析構函數,刪除m_a指向的地址,然而f1也會調用析構函數,由于f1和f的m_a指向同一個地址,那就好重復訪問,訪問一個被刪除的地址肯定會報錯的;因此我們需要對賦值運算符進行重載,這里提示一下,連等就相當于鏈式調用,因此重載運算符的返回值類型需要返回引用。

具體實現

Info& operator=(Info& f)
    {
        if (m_a != NULL)
            delete m_a;
        m_a = NULL;
        m_a = new int(*f.m_a);
        return *this;
    }

返回值類型是類引用,這樣可以做到鏈式調用 ,函數名還是統一的operator+運算符,既然是賦值運算符就用operator=,然后這個重載發生在成員內部,因此參數里只需要傳入用來賦值的對象即可,注意倒數第二行代碼,我利用new讓m_a指向堆區中新開辟的地址,這是賦值運算符重載的關鍵;就是因為把地址指向了堆區的新地址,這樣不同的對象在調用析構函數的時候各刪各的堆地址,不會訪問空地址,這個問題的解決和深淺拷貝的解決方式一樣,都是自己寫方法來避免原來方法中成員屬性指向同一個地址。最后返回自身的引用,就可以實現連續調用了。

關系運算符重載

關系運算符有“大于”、“小于”、“等于”、“大于等于”、“不等于”等幾種情況,我就舉例等于和不等于兩種賦值運算符重載的例子

類結構

class Info
{
    friend void test1();
    int* m_a;
    string m_name;
public:
    Info()
    {
        m_a = NULL;
    }
    Info(int a,string name)
    {
        m_a = new int(a);
        m_name = name;
    }
    ~Info()
    {
        if (m_a != NULL)
            delete m_a;
        m_a = NULL;
    }
}

這里的類結構相比于賦值運算符重載多了一個String類型的m_name屬性,然后寫出類的無參、有參構造和析構函數,最上面的friend關鍵字是加了一個友元的聲明,讓下面的test1函數可以訪問類的私有屬性。

具體實現

    bool operator==(Info& f)
    {
        if (*this->m_a == *f.m_a && m_name==f.m_name)
            return true;
        else return false;
    }
    bool operator!=(Info& f)
    {
        if (*this->m_a == *f.m_a && m_name == f.m_name)
            return false;
        else return true;
    }

返回值類型寫成布爾類型,因為關系運算的結果就是布爾類型的,常和while循環以及if語句使用;函數名還是老樣子,operator==和operator!=,分別是相等和不等;既然是成員內部的關系運算符重載,那么形參傳入一個待比較對象即可。

調用方法

void test1()
{
    Info f1(20,"張三");
    Info f3(30,"張六");
    if (f1== f3) cout << "二者相等" << endl;
    else if (f1!= f3) cout << "二者不相等" << endl;
}

運行效果?

函數調用運算符重載

函數調用使用“()”,函數調用也是可以重載的,而且重載的調用很像直接調用函數,因此也叫做仿函數。

類結構

class MyHello
{
public:
    string hello;
};

非常簡單的類結構,只有一個公有權限下的String類型的hello屬性。

具體實現

    void operator()(string s)
    {
        cout << s << endl;
    }

因為只是打印一下,不需要返回值,函數名不多說了,和前面類似,然后傳入字符串類型再方法里打印出來。

調用方法?

void test()
{
    MyHello hello;
    hello("Hello World");
}

首先創建類對象hello,直接使用重載后的調用方法:對象+(字符串);這樣就能打印出引號里的內容了:

匿名對象調用

最后補充一個匿名對象的知識,示例:

class MyAdd
{
public:
    int operator()(int num1, int num2)
    {
        return num1 + num2;
    }
};
void test1()
{
    MyAdd myAdd;
    int num = myAdd(160, 40);
    cout << "ret =" << myAdd(160,40) << endl;
    cout << "ret =" << MyAdd()(100,50) << endl;
}

這里我寫了一個只有重載函數調用函數的類,并在test1中用常規和匿名對象調用重載后的函數調用方法;看一下運行效果:

先創建對象,再通過對象調用函數的方法我們不感到奇怪,但是最后一個輸出語句中,MyAdd()(100,50)是什么意思呢 ,這就是匿名對象,往后我們遇到形如類名+()再+調用函數的方式,那就是創建了匿名對象,其特點就是創建完畢后就會刪除,這里我們只都一下數據,所以適合匿名對象的調用。

總結

到這里C++的運算符重載徹底結束了,運算符重載可以多個都重載并互相配合使用,把對象的屬性可以和基本類型一樣進行算數運算和邏輯運算,在類對象比較多的時候可以節省很多時間,簡化程序。

原文鏈接:https://blog.csdn.net/m0_58618795/article/details/125250061

欄目分類
最近更新