C++語言學(xué)習(xí)(八)——操作符重載

C++語言學(xué)習(xí)(八)——操作符重載

一、操作符重載基礎(chǔ)

1、操作符重載的語法

通過operator關(guān)鍵字可以定義特殊的函數(shù),operator本質(zhì)是通過函數(shù)重載操作符。

創(chuàng)新互聯(lián)專注于晉安企業(yè)網(wǎng)站建設(shè),響應(yīng)式網(wǎng)站設(shè)計,成都商城網(wǎng)站開發(fā)。晉安網(wǎng)站建設(shè)公司,為晉安等地區(qū)提供建站服務(wù)。全流程按需定制開發(fā),專業(yè)設(shè)計,全程項目跟蹤,創(chuàng)新互聯(lián)專業(yè)和態(tài)度為您提供的服務(wù)

Type operator operatorname(const Type p1, const Type p2)
{
    Type ret;

    return ret;
}

2、友元函數(shù)重載操作符

可以將操作符重載函數(shù)聲明為友元函數(shù)。

#include <iostream>

using namespace std;

class Complex
{
public:
    Complex(float x=0, float y=0)
    {
        this->x = x;
        this->y = y;
    }
    void print()
    {
        cout<<"("<<x<<","<<y<<")"<<endl;
    }
    friend const Complex operator+(const Complex &c1,const Complex &c2);
private:
    float x;
    float y;
};
const Complex operator+(const Complex &c1,const Complex &c2)
{
    return Complex(c1.x + c2.x,c1.y + c2.y);
}
int main(int argc, char *argv[])
{
    Complex c1(2,3);
    Complex c2(3,4);
    c1.print();
    c2.print();
    Complex c3 = c1 + c2;
    c3.print();
    Complex c4 = operator+(c1,c2);
    c4.print();

    return 0;
}

上述代碼中,編譯器會檢查是否有可用的操作符重載函數(shù),因此Complex c3 = c1 + c2;代碼也是合法的。

3、成員函數(shù)重載操作符

將操作符重載函數(shù)定義為類成員函數(shù)。

#include <iostream>

using namespace std;

class Complex
{
public:
    Complex(float x=0, float y=0)
    {
        this->x = x;
        this->y = y;
    }
    void print()
    {
        cout<<"("<<x<<","<<y<<")"<<endl;
    }
    const Complex operator+(const Complex &another)
    {
        cout << "member function." << endl;
        return Complex(this->x + another.x, this->y + another.y);
    }
    friend const Complex operator+(const Complex &c1,const Complex &c2);
private:
    float x;
    float y;
};
const Complex operator+(const Complex &c1,const Complex &c2)
{
    cout << "friend global function." << endl;
    return Complex(c1.x + c2.x,c1.y + c2.y);
}
int main(int argc, char *argv[])
{
    Complex c1(2,3);
    Complex c2(3,4);
    c1.print();
    c2.print();
    //成員函數(shù)
    Complex c3 = c1 + c2;
    c3.print();
    //成員函數(shù)
    Complex c4 = c1.operator +(c2);
    c4.print();
    //全局函數(shù)
    Complex c5 = operator+(c1,c2);
    c4.print();

    return 0;
}

操作符重載函數(shù)作為類的成員函數(shù)時,比全局操作符重載函數(shù)少一個參數(shù),不需要依賴友元就可以完成操作符重載,編譯器會優(yōu)先在類的成員函數(shù)中查找操作符重載函數(shù)。因此Complex c3 = c1 + c2;代碼會優(yōu)先調(diào)用類的操作符重載成員函數(shù)。

4、操作符重載的規(guī)則

操作符重載的規(guī)則:
A、C++不允許用戶自己定義新的運(yùn)算符,只能對已有的 C++運(yùn)算符進(jìn)行重載。
B、C++語言中大部分運(yùn)算符都可以重載,成員選擇符(.)、成員對象選擇符(.*)、域解析操作符(::)、條件操作符(?:)、sizeof不可以重載。除了賦值操作符(=)外,基類中重載的操作符都將被派生類繼承。
C、重載不能改變運(yùn)算符運(yùn)算對象(即操作數(shù))的個數(shù)。
D、重載不能改變運(yùn)算符的優(yōu)先級別。
E、重載不能改變運(yùn)算符的結(jié)合性。
F、重載運(yùn)算符的函數(shù)不能有默認(rèn)的參數(shù)
G、重載的運(yùn)算符必須和用戶定義的自定義類型的對象一起使用,其參數(shù)至少應(yīng)有一個是類對象(或類對象的引用)。參數(shù)不能全部是 C++的標(biāo)準(zhǔn)類型,以防止用戶修改用于標(biāo)準(zhǔn)類型數(shù)據(jù)成員的運(yùn)算符的性質(zhì)。
H、用于類對象的運(yùn)算符一般必須重載,但有兩個例外,運(yùn)算符”=“和運(yùn)算符”&“不必用戶重載。
I、應(yīng)當(dāng)使重載運(yùn)算符的功能類似于該運(yùn)算符作用于標(biāo)準(zhǔn)類型數(shù)據(jù)時候時所實(shí)現(xiàn)的功能。
J、運(yùn)算符重載函數(shù)可以是類的成員函數(shù),也可以是類的友元函數(shù),還可以是既非類的成員函數(shù)也不是友元函數(shù)的普通函數(shù)。
K、賦值操作符只能重載為成員函數(shù)

二、操作符重載實(shí)例

1、雙目運(yùn)算符重載

形式:L#R
全局函數(shù):operator#(L,R);
成員函數(shù):L.operator#(R)
operator+=實(shí)例:

#include <iostream>
using namespace std;
class Complex
{
public:
    Complex(double x = 0, double y = 0)
    {
        this->x = x;
        this->y = y;
    }
    void print()
    {
        cout<<"("<<x<<","<<y<<")"<<endl;
    }
    Complex& operator +=(const Complex &c)
    {
        this->x += c.x;
        this->y += c.y;
        return * this;
    }
private:
    double x;
    double y;
};

2、單目運(yùn)算符重載

形式:#M 或 M#
全局函數(shù):operator#(M)
成員函數(shù):M.operator#()
operator-實(shí)例:

#include <iostream>
using namespace std;
class Complex
{
public:
    Complex(double x = 0, double y = 0)
    {
        this->x = x;
        this->y = y;
    }
    void print()
    {
        cout<<"("<<x<<","<<y<<")"<<endl;
    }
    const Complex operator-(void) const
    {
        return Complex(-x,-y);
    }
private:
    double x;
    double y;
};

3、流輸入輸出運(yùn)算符重載

函數(shù)形式

    istream & operator>>(istream &,自定義類&);
    ostream & operator<<(ostream &,自定義類&);

流輸入輸出運(yùn)算符重載通過友元來實(shí)現(xiàn),避免修改C++的標(biāo)準(zhǔn)庫。
operator<< 和operator>>實(shí)例:

class Complex
{
public:
    Complex(double x = 0, double y = 0)
    {
        this->x = x;
        this->y = y;
    }
    void print()
    {
        cout<<"("<<x<<","<<y<<")"<<endl;
    }
    friend ostream & operator<<(ostream &os, const Complex & c);
    friend istream & operator>>(istream &is, Complex &c);
private:
    double x;
    double y;
};
ostream & operator<<(ostream &os, const Complex & c)
{
    os<<"("<<c.x<<","<<c.y<<")";
    return os;
}
istream & operator>>(istream &is, Complex &c)
{
    is>>c.x>>c.y;
    return is;
}

三、操作符重載總結(jié)

1、不可以重載的操作符

. (成員訪問運(yùn)算符)
.* (成員指針訪問運(yùn)算符)
:: (域運(yùn)算符)
sizeof (長度運(yùn)算符)
?: (條件運(yùn)算符)

2、只能重載為成員函數(shù)的運(yùn)算符

= 賦值運(yùn)算符
[] 下標(biāo)運(yùn)算符
() 函數(shù)運(yùn)算符
-> 間接成員訪問
編譯器默認(rèn)重載了賦值運(yùn)算符,但編譯器默認(rèn)重載的賦值操作符僅完成淺拷貝,需要深拷貝操作必須自定義重載賦值操作符。

3、運(yùn)算符重載與友元

A、一個操作符的左右操作數(shù)不一定是相同類型的對象,這就涉及到將該操作符函數(shù)定義為誰的友元,誰的成員問題。
B、一個操作符函數(shù),被聲明為哪個類的成員,取決于該函數(shù)的調(diào)用對象(通常是左操作數(shù))。
C、一個操作符函數(shù),被聲明為哪個類的友員,取決于該函數(shù)的參數(shù)對象(通常是右操作數(shù))。

#include <iostream>
using namespace std;
class Mail;
class Sender
{
public:
    Sender(string s):_addr(s){}
    Sender& operator<<(const Mail & mail); //成員
private:
    string _addr;
};
class Mail
{
public:
    Mail(string _t,string _c ):_title(_t),_content(_c){}
    friend Sender& Sender::operator<<(const Mail & mail);
    //友元
private:
    string _title;
    string _content;
};
Sender& Sender::operator<<(const Mail & mail)
{
    cout<<"Address:"<<mail._addr<<endl;
    cout<<"Title :"<<mail._title<<endl;
    cout<<"Content:"<<mail._content<<endl;
    return *this;
}
int main()
{
    Sender sender("guilin_wang@163.com");
    Mail mail("note","meeting at 3:00 pm");
    Mail mail2("tour","One night in beijing");
    sender<<mail<<mail2;
    return 0;
}

5、操作符重載的陷阱

A、邏輯運(yùn)算操作符:
運(yùn)算符重載本質(zhì)是函數(shù)重載,C++對邏輯操作符重載時將邏輯操作符定義為函數(shù),但是由于函數(shù)參數(shù)的計算次序是不確定的,導(dǎo)致邏輯操作符原生的短路法則將失效,因此不推薦對邏輯操作符進(jìn)行重載。工程實(shí)踐中需要使用重載比較操作符等方法避免重載邏輯操作符的陷阱,直接使用成員函數(shù)代替邏輯操作符重載,使用全局函數(shù)對邏輯操作符進(jìn)行重載。

#include <iostream>

using namespace std;

class Test
{
public:
    Test(int ok = true)
    {
        this->ok = ok;
    }
    int value()const
    {
        cout << "call value(),ok = " << ok << endl;
        return ok;
    }
    Test operator +(const Test& another)
    {
        this->ok += another.ok;
        return *this;
    }
private:
    int ok;
};
//&&操作符重載函數(shù)
bool operator &&(const Test& left, const Test& right)
{
    return left.value() && right.value();
}
//||操作符重載函數(shù)
bool operator ||(const Test& left, const Test& right)
{
    return left.value() || right.value();
}

Test func(Test test)
{
    cout << "Test func(Test test): i = "<< test.value() <<endl;
    return test;
}

int main(int argc, char *argv[])
{
    Test test0(0);
    Test test1(1);
    Test test2(2);
    Test test3(3);
    if(test0 && test1)
    {
        cout << "result is true" << endl;
    }
    else
    {
        cout << "result is false" << endl;
    }
    /*****************************
     *call value(),ok = 0
     *result is false
     * 上述測試代碼:短路法則正常
     * **************************/
    cout << endl;
    if(operator &&(func(test0), func(test1)))
    {
        cout << "result is true" << endl;
    }
    else
    {
        cout << "result is false" << endl;
    }
    cout << endl;
    /*****************************
     *call value(),ok = 1
     *Test func(Test test): i = 1
     *call value(),ok = 0
     *Test func(Test test): i = 0
     *call value(),ok = 0
     *result is false
     *上述測試代碼:短路法則失效
     * **************************/
    if((test2 + test3) && test0)
    {
        cout << "result is true" << endl;
    }
    else
    {
        cout << "result is false" << endl;
    }
    cout << endl;
    /*****************************
     *call value(),ok = 5
     *call value(),ok = 0
     *result is false
     * **************************/
    if(test0 || test1)
    {
        cout << "result is true" << endl;
    }
    else
    {
        cout << "result is false" << endl;
    }
    cout << endl;
    /*****************************
     *call value(),ok = 0
     *call value(),ok = 1
     *result is true
     * **************************/
    if(operator &&(test0, test1))
    {
        cout << "result is true" << endl;
    }
    else
    {
        cout << "result is false" << endl;
    }
    cout << endl;
    /*****************************
     *call value(),ok = 0
     *result is false
     *上述測試代碼:短路法則正常
     * **************************/
    if(operator ||(test0 + test1, test3))
    {
        cout << "result is true" << endl;
    }
    else
    {
        cout << "result is false" << endl;
    }
    /*****************************
     *call value(),ok = 1
     *result is true
     *上述測試代碼:短路法則正常
     * **************************/

    return 0;
}

上述測試代碼中,如果邏輯操作符的操作數(shù)中是需要計算的函數(shù)調(diào)用,短路法則可能會失效。
B、逗號操作符:
可以使用全局函數(shù)對逗號操作符進(jìn)行重載,重載函數(shù)的參數(shù)必須有一個是類類型,返回值類型必須是引用。

class& operator,(const class& a, const class& b)
{
    return const_cast<class&>(b);
}

重載逗號操作符后,逗號表達(dá)式無法嚴(yán)格從左向右計算表達(dá)式,不能重載逗號操作符,重載后的逗號操作符沒有了原生的語義。
原因:操作符的重載本質(zhì)是函數(shù)調(diào)用,函數(shù)調(diào)用在進(jìn)入函數(shù)體前需要完成所有參數(shù)的計算,參數(shù)的計算次序是不確定的,因此重載逗號操作符后無法保證逗號操作符的原生語義。
逗號操作符不需要重載,重載的逗號操作符無法嚴(yán)格從左向右計算逗號表達(dá)式,失去了原生逗號操作符的語義。
C、前置操作符與后置操作符
前置操作符和后置操作符支持全局函數(shù)、類成員函數(shù)重載。
前置的++、--運(yùn)算操作符可以重載,不需要額外的參數(shù)。
后置的++、--運(yùn)算操作符可以重載,需要一個int類型的占位參數(shù)。

#include <iostream>

using namespace std;

class Test
{
public:
    Test(int i = 0)
    {
        this->i = i;
    }
    //前置操作符++
    Test& operator ++()
    {
        ++i;
        return *this;
    }
    //前置操作符--
    Test& operator --()
    {
        --i;
        return *this;
    }
    //后置操作符--
    Test operator ++(int)
    {
        Test ret(i);
        i++;
        return ret;
    }
    //后置操作符--
    Test operator --(int)
    {
        Test ret(i);
        i--;
        return ret;
    }
    int value()const
    {
        return i;
    }
private:
    int i;
};

int main(int argc, char *argv[])
{
    Test test1(1);
    cout << (++test1).value() << endl;
    Test test2(1);
    cout << (--test2).value() << endl;
    Test test3(1);
    cout << (test3++).value() << endl;
    Test test4(1);
    cout << (test4--).value() << endl;

    return 0;
}

由于類的前置操作符重載函數(shù)內(nèi)部沒有額外的臨時對象開銷,類的前置操作符重載函數(shù)效率比后置操作符高。

    int i = 0;
    i++;
    ++i;

對于C++基礎(chǔ)類型,前置操作符和后置操作符效率基本相同。
現(xiàn)代C++編譯器會對編譯代碼進(jìn)行優(yōu)化,使得編譯后的二進(jìn)制代碼更加高效,優(yōu)化后的二進(jìn)制代碼可能失去C/C++代碼的原生語義。

三、類型轉(zhuǎn)換

1、類型轉(zhuǎn)換簡介

C++語言中,標(biāo)準(zhǔn)類型之間的轉(zhuǎn)換一般有隱式和顯示轉(zhuǎn)換,用戶自定義類型間的轉(zhuǎn)換則需要自定義專門的轉(zhuǎn)換函數(shù)。
C語言中,基本類型間會進(jìn)行隱式的類型安全轉(zhuǎn)換,轉(zhuǎn)換規(guī)則如下:
C++語言學(xué)習(xí)(八)——操作符重載

 int a = -2000;
 unsigned int b = 1000;
 cout << a + b << endl;//4294966296

上述代碼中,int與unsigned int運(yùn)算時int會被轉(zhuǎn)換為unsigned int,此時a會被轉(zhuǎn)換為unsigned int,是一個非常大的數(shù)。

short s = 12;
char c = '1';
cout << sizeof(s + c) << endl;//4

上述代碼中,C++編譯器會進(jìn)行優(yōu)化,編譯器遇到short與char進(jìn)行運(yùn)算時會將short和char都轉(zhuǎn)換為int,便于高效計算。
C++語言兼容了C語言的隱式類型安全轉(zhuǎn)換。

2、標(biāo)準(zhǔn)類型間轉(zhuǎn)換

基本類型間的轉(zhuǎn)換如下:
A、隱式轉(zhuǎn)換
5.0/8
B、顯示轉(zhuǎn)換
(float)5/8

3、C++類類型的轉(zhuǎn)換

C++的類類型之間的轉(zhuǎn)換的規(guī)則如下:
A、轉(zhuǎn)換函數(shù)定義在源對象類(待轉(zhuǎn)換對象中)中,是轉(zhuǎn)換源的成員函數(shù)。
B、一旦為轉(zhuǎn)換源類型提供了到目標(biāo)類型的轉(zhuǎn)化操作符函數(shù),就可以將源類型對象以隱式轉(zhuǎn)化的方式得的目標(biāo)類型的對象。
C、應(yīng)用于構(gòu)造及初始化,賦值,傳參,返回等等場合。

#include <iostream>

using namespace std;

class Test
{
public:
    Test(int i = 0)
    {
        this->i = i;
        cout << "Test(int i = 0) i = " << i << endl;
    }
private:
    int i;
};

int main(int argc, char *argv[])
{
    Test test;//Test(int i = 0) i = 0
    test = 10;//Test(int i = 0) i = 10

    return 0;
}

上述代碼中,編譯器會將10使用構(gòu)造函數(shù)Test(int i = 0)隱式轉(zhuǎn)換為Test對象。
實(shí)際工程中類的隱式類型轉(zhuǎn)換是不安全的,編譯器會盡力去查找構(gòu)造函數(shù)轉(zhuǎn)化不同的類型,如果沒有匹配的構(gòu)造函數(shù)才會報錯,因此不可以使用隱式類型轉(zhuǎn)換,需要使用explicit關(guān)鍵字聲明編譯器不能隱式類型轉(zhuǎn)換,而需要顯示的聲明類型轉(zhuǎn)換。
顯示聲明類對象類型轉(zhuǎn)換的使用方式:

static_cast<classname>(value);
classname(value);
(calssname)value;//不推薦
#include <iostream>

using namespace std;

class Test
{
public:
    explicit Test(int i = 0)
    {
        this->i = i;
        cout << "Test(int i = 0) i = " << i << endl;
    }
private:
    int i;
};

int main(int argc, char *argv[])
{
    Test test;//Test(int i = 0) i = 0
    test = static_cast<Test>(10);//Test(int i = 0) i = 10
    test = Test(100);//Test(int i = 0) i = 100

    return 0;
}

上述代碼中,構(gòu)造函數(shù)使用explicit關(guān)鍵字進(jìn)行聲明,編譯器不能再進(jìn)行隱式的類型轉(zhuǎn)換,只能使用顯示的類型轉(zhuǎn)換。

4、用類型轉(zhuǎn)換構(gòu)造函數(shù)進(jìn)行類型轉(zhuǎn)換

類型轉(zhuǎn)換構(gòu)造函數(shù)聲明如下:
classname(const anotherclass & another);

#include <iostream>

using namespace std;

class Point3D;
class Point2D
{
public:
    Point2D(int x = 0,int y = 0)
    {
        this->x = x;
        this->y = y;
    }
    void print()
    {
        cout<<"("<<x<<","<<y<<")"<<endl;
    }
    friend class Point3D;
private:
    int x;
    int y;
};
class Point3D
{
public:
    Point3D(int x = 0, int y = 0, int z = 0)
    {
        this->x = x;
        this->y = y;
        this->z = z;
    }
    //類型轉(zhuǎn)換構(gòu)造函數(shù)
    Point3D(const Point2D &p)
    {
        this->x = p.x;
        this->y = p.y;
        this->z = 0;
        cout << "Point3D(const Point2D &p)" <<endl;
    }
    void print()
    {
        cout<<"("<<x<<","<<y<<","<<z<<")"<<endl;
    }
private:
    int x;
    int y;
    int z;
};

int main(int argc, char *argv[])
{
    Point2D p2(1,2);
    p2.print();
    Point3D p3(3,4,5);
    p3.print();
    Point3D p3a = p2;//Point3D(const Point2D &p)
    p3a.print();

    return 0;
}

上述代碼中,Point3D類提供了一個類型轉(zhuǎn)換構(gòu)造函數(shù),用于將Point2D類對象轉(zhuǎn)換為Point3D類型。

5、用類型轉(zhuǎn)換操作符函數(shù)進(jìn)行轉(zhuǎn)換

類型轉(zhuǎn)換函數(shù)可以將類對象轉(zhuǎn)換為其它類型。
類型轉(zhuǎn)換函數(shù)聲明的語法如下:
operator Type(void);

#include <iostream>

using namespace std;

class Point3D;
class Point2D
{
public:
    explicit Point2D(int x = 0,int y = 0)
    {
            this->x = x;
            this->y = y;
    }
    void print()
    {
            cout<<"("<<x<<","<<y<<")"<<endl;
    }
private:
    int x;
    int y;
    friend class Point3D;
};
class Point3D
{
public:
    explicit Point3D(int x = 0, int y = 0, int z = 0)
    {
            this->x = x;
            this->y = y;
            this->z = z;
    }
    //類型轉(zhuǎn)換構(gòu)造函數(shù)
    Point3D(const Point2D &p)
    {
            this->x = p.x;
            this->y = p.y;
            this->z = 0;
            cout << "Point3D(const Point2D &p)" <<endl;
    }
    operator Point2D()
    {
            cout << "operator Point2D()" << endl;
            Point2D p2;
            p2.x = x;
            p2.y = y;
            return p2;
    }
    void print()
    {
            cout<<"("<<x<<","<<y<<","<<z<<")"<<endl;
    }
private:
    int x;
    int y;
    int z;
};

int main(int argc, char *argv[])
{
    Point3D p3(3,4,5);
    p3.print();
    Point2D p2(1,2);
    p2.print();

    Point2D p2a = p3;//operator Point2D()
    p2a.print();

    return 0;
}

上述代碼中,使用Point3D對象對Point2D對象進(jìn)行初始化時會調(diào)用operator Point2D()類型轉(zhuǎn)換操作符函數(shù)。
類型轉(zhuǎn)換操作符函數(shù)可能和類型轉(zhuǎn)換構(gòu)造函數(shù)沖突,可以使用explicit對類型轉(zhuǎn)換構(gòu)造函數(shù)聲明避免沖突。工程中實(shí)際使用普通的classname toClassName()公有成員函數(shù)進(jìn)行類型轉(zhuǎn)換。

#include <iostream>

using namespace std;

class Point3D;
class Point2D
{
public:
    explicit Point2D(int x = 0,int y = 0)
    {
        this->x = x;
        this->y = y;
    }
    void print()
    {
        cout<<"("<<x<<","<<y<<")"<<endl;
    }
private:
    int x;
    int y;
    friend class Point3D;
};
class Point3D
{
public:
    explicit Point3D(int x = 0, int y = 0, int z = 0)
    {
        this->x = x;
        this->y = y;
        this->z = z;
    }
    //類型轉(zhuǎn)換構(gòu)造函數(shù)
    Point3D(const Point2D &p)
    {
        this->x = p.x;
        this->y = p.y;
        this->z = 0;
        cout << "Point3D(const Point2D &p)" <<endl;
    }
    operator Point2D()
    {
        cout << "operator Point2D()" << endl;
        Point2D p2;
        p2.x = x;
        p2.y = y;
        return p2;
    }
    Point2D toPoint2D()
    {
        Point2D p2;
        p2.x = x;
        p2.y = y;
        return p2;
    }
    void print()
    {
        cout<<"("<<x<<","<<y<<","<<z<<")"<<endl;
    }
private:
    int x;
    int y;
    int z;
};

int main(int argc, char *argv[])
{
    Point3D p3(3,4,5);
    p3.print();
    Point2D p2(1,2);
    p2.print();

    Point2D p2a = p3;//operator Point2D()
    p2a.print();

    Point2D p2b = p3.toPoint2D();
    p2b.print();

    return 0;
}

五、操作符重載應(yīng)用

1、函數(shù)操作符

函數(shù)對象也成仿函數(shù)(functor),可以使用具體的類對象取代類成員函數(shù)。函數(shù)對象通過重載函數(shù)操作符實(shí)現(xiàn),函數(shù)操作符只能重載為類的成員函數(shù),可以定義不同參數(shù)的多個重載函數(shù)。
函數(shù)操作符重載函數(shù)聲明如下:
Type operator()()
函數(shù)操作符主要應(yīng)用于STL和模板。函數(shù)操作符只能通過類成員函數(shù)重載,函數(shù)對象用于在工程中取代函數(shù)指針。

#include <iostream>
using namespace std;

class Fib
{
 private:
    int a0;
    int a1;
public:
    Fib()
    {
        a0 = 0;
        a1 = 1;
    }
    Fib(int n)
    {
        a0 = 0;
        a1 = 1;
        for(int i = 0; i < n; i++)
        {
            int t = a1;
            a1 = a0 + a1;
            a0 = t;
        }
    }
    int operator()()
    {
        int ret = a1;
        a1 = a0 + a1;
        a0 = ret;
        return ret;
    }
};

int main()
{
    Fib fib;
    for(int i = 0; i < 10; i++)
    {
        cout << fib() << endl;
    }
    cout << endl;
    Fib fib2(10);//從第10項開始
    for(int i = 0; i < 5; i++)
    {
        cout << fib2() << endl;
    }
    return 0;
}

2、堆內(nèi)存操作符

定義:

operator new
operator delete
operator new[]
operator delete[]

A、全局函數(shù)重載

#include <iostream>
#include <stdlib.h>
using namespace std;

class A
{
public:
    A()
    {
        cout<<"A constructor"<<endl;
    }
    ~A()
    {
        cout<<"A destructor"<<endl;
    }
private:
    int a;
};

void * operator new (size_t size)
{
    cout<<"new "<<size<<endl;
    return malloc(size);
}
void operator delete(void *p)
{
    cout<<"delete"<<endl;
    free(p);
}
void * operator new[] (size_t size)
{
    cout<<"new[] "<<size<<endl;
    return malloc(size);
}
void operator delete[](void *p)
{
    cout<<"delete[] "<<endl;
    free(p);
}

int main()
{
    int *p = new int;
    delete p;
    int *pa = new int[20];
    delete []pa;
    A * cp = new A;
    delete cp;
    A * cpa = new A[20];
    delete []cpa;
    return 0;
}

B、類成員函數(shù)重載

#include <iostream>
#include <stdlib.h>
using namespace std;

class A
{
public:
    A()
    {
        cout<<"A constructor"<<endl;
    }
    ~A()
    {
        cout<<"A destructor"<<endl;
    }
    void * operator new (size_t size)
    {
        cout<<"new "<<size<<endl;
        return malloc(size);
    }
    void operator delete(void *p)
    {
        cout<<"delete"<<endl;
        free(p);
    }
    void * operator new[] (size_t size)
    {
        cout<<"new[] "<<size<<endl;
        return malloc(size);
    }
    void operator delete[](void *p)
    {
        cout<<"delete[] "<<endl;
        free(p);
    }
    private:
        int a;
};

int main()
{
    // int *p = new int;
    // delete p;
    // int *pa = new int[20];
    // delete []pa;
    A * cp = new A;
    delete cp;
    A * cpa = new A[20];
    delete []cpa;
    return 0;
}

3、賦值操作符重載

編譯器默認(rèn)為每個類重載了賦值操作符,但默認(rèn)的賦值操作符只完成淺拷貝。與拷貝構(gòu)造函數(shù)一樣,當(dāng)需要深拷貝時需要顯示重載賦值操作符。

#include <iostream>
using namespace std;

class Test
{
private:
    int* pointer;
public:
    Test()
    {
        pointer = NULL;
    }
    Test(int n)
    {
        pointer = new int(n);
    }
    Test(const Test& another)
    {
        pointer = new int(*another.pointer);
    }
    Test& operator=(const Test& another)
    {
        if(this != &another)
        {
            delete pointer;
            pointer = new int(*another.pointer);
        }
        return *this;
    }
    void print()
    {
        cout << this << endl;
    }

};

int main()
{
    Test t1 = 1;
    Test t2 = t1;
    Test t3;
    t3 = t2;
    t1.print();
    t2.print();
    t3.print();
    return 0;
}

4、下標(biāo)訪問操作符重載``

下標(biāo)訪問操作符([])只能通過類的成員函數(shù)重載,并且重載函數(shù)只能使用一個參數(shù)。
#include <iostream>
#include <sstream>
#include <string>

using namespace std;

class Test
{
int m_array[5];
public:
//使用位置索引作為下標(biāo)訪問
int& operator [](int index)
{
return m_array[index];
}
//使用字符串作為下標(biāo)訪問
int& operator [](const char* index)
{
if(index == "1st")
{
return m_array[0];
}
if(index == "2nd")
{
return m_array[1];
}
if(index == "3rd")
{
return m_array[2];
}
if(index == "4th")
{
return m_array[3];
}
if(index == "5th")
{
return m_array[4];
}
return m_array[0];
}
int length()const
{
return sizeof(m_array)/sizeof(int);
}
};

int main(int argc, char *argv[])
{
Test test;
for(int i = 0; i < test.length(); i++)
{
test[i] = i;
}
for(int i = 0; i < test.length(); i++)
{
cout << test[i] << endl;
}

cout << test["1st"] << endl;
cout << test["2nd"] << endl;
cout << test["3rd"] << endl;
cout << test["4th"] << endl;
cout << test["5th"] << endl;
return 0;

}

本文題目:C++語言學(xué)習(xí)(八)——操作符重載
當(dāng)前URL:http://bm7419.com/article14/ijphde.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供電子商務(wù)、網(wǎng)站策劃、網(wǎng)頁設(shè)計公司網(wǎng)站排名、網(wǎng)站制作軟件開發(fā)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

成都定制網(wǎng)站建設(shè)