C++運(yùn)算符重載

友元

友元函數(shù)

友元函數(shù)是定義在類外部,但有權(quán)訪問(wèn)類的所有私有(private)成員和保護(hù)(protected)成員。盡管友元函數(shù)的原型有在類的定義中出現(xiàn)過(guò),但是友元函數(shù)并不是成員函數(shù)。

關(guān)鍵字friend
friend 返回值類型 函數(shù)名(參數(shù)列表);
friend void global_printf(Point const that);    //友元函數(shù)

友元類

友元類的所有成員函數(shù)都是另一個(gè)類的友元函數(shù),都可以訪問(wèn)另一個(gè)類中的隱藏信息(包括私有成員和保護(hù)成員)

//類前面加上friend聲明友元類
class Point
{
    int m_x;
    int m_y;
public:
    friend class Point3D;//友元類
};
class Point3D
{
    Point m_p;
    int m_z;
public:
};

注意事項(xiàng):

  1. 只有友元可以訪問(wèn),其他依然不能訪問(wèn)。

若類B是類A的友元。則只有類B的成員函數(shù)可以訪問(wèn)類A中的隱藏信息

  1. 友元是單向的,不具有交換性。

若類B是類A的友元,類A不一定是類B的友元,要看在類中是否有相應(yīng)的聲明。

  1. 友元關(guān)系不具有傳遞性。

若類B是類A的友元,類C是B的友元,類C不一定是類A的友元,同樣要看類中是否有相應(yīng)的申明

友元類以及友元函數(shù)示例程序

//demo1.cpp
#include<iostream>
using namespace std;
class Point
{
    int m_x;
    int m_y;
public:
    Point(int x = 0, int y = 0);    //缺省構(gòu)造函數(shù)    類內(nèi)聲明類外定義
    void Point_printf();            //類內(nèi)數(shù)據(jù)打印函數(shù)
    friend void global_printf(Point const that);    //友元函數(shù) 類外數(shù)據(jù)打印函數(shù)
    friend class Point3D;           //友元類
};
class Point3D
{
    Point m_p;
    int m_z;
public:
    Point3D(int x = 0, int y = 0, int z = 0);
    void Point3D_printf();
};
int main()
{
    Point point(10,20);
    cout << "========類函數(shù)打印========" << endl;
    point.Point_printf();
    cout << "========友元函數(shù)打印========" << endl;
    global_printf(point);
    cout << "========友元類打印========" << endl;
    Point3D point3d(10, 20, 30);
    point3d.Point3D_printf();
    cin.get();
    return 0;
}

Point::Point(int x, int y)
{
    m_x = x;
    m_y = y;
}

void Point::Point_printf()
{
    cout << this->m_x << " " << this->m_y << endl;
}

void global_printf(Point const that)
{
    cout << that.m_x << " " << that.m_y << endl;
}

Point3D::Point3D(int x, int y, int z)
{
    m_p.m_x = x;
    m_p.m_y = y;
    m_z = z;
}

void Point3D::Point3D_printf()
{
    cout << m_p.m_x << " " << m_p.m_y << " " << m_z << endl;
}

打印結(jié)果:

========類函數(shù)打印========
10 20
========友元函數(shù)打印========
10 20
========友元類打印========
10 20 30

運(yùn)算符重載

運(yùn)算符重載,就是對(duì)已有的運(yùn)算符重新進(jìn)行定義,賦予其另一種功能,以適應(yīng)不同的數(shù)據(jù)類型。

重載運(yùn)算符可以使用成員函數(shù)非成員函數(shù)(一般是友元函數(shù))兩種方法

只能使用其中的一種方法

關(guān)鍵字operator

類名 operator運(yùn)算符(const 類名& other);//成員函數(shù)實(shí)現(xiàn)
Complex operator+(const Complex& other);

可重載運(yùn)算符

雙目算術(shù)運(yùn)算符 + (加),-(減),*(乘),/(除),% (取模)
關(guān)系運(yùn)算符 ==(等于),!= (不等于),< (小于),> (大于>,<=(小于等于),>=(大于等于)
邏輯運(yùn)算符 ||(邏輯或),&&(邏輯與),!(邏輯非)
單目運(yùn)算符 + (正),-(負(fù)),*(指針),&(取地址)
自增自減運(yùn)算符 ++(自增),--(自減)
位運(yùn)算符 | (按位或),& (按位與),~(按位取反),^(按位異或),,<< (左移),>>(右移)
賦值運(yùn)算符 =, +=, -=, *=, /= , % = , &=, |=, ^=, <<=, >>=
空間申請(qǐng)與釋放 new, delete, new[ ] , delete[]
其他運(yùn)算符 ()(函數(shù)調(diào)用),->(成員訪問(wèn)),,(逗號(hào)),[](下標(biāo))

不可重載的運(yùn)算符

  • .:成員訪問(wèn)運(yùn)算符
  • .*, ->*:成員指針訪問(wèn)運(yùn)算符
  • :::域運(yùn)算符
  • sizeof:長(zhǎng)度運(yùn)算符
  • ?::條件運(yùn)算符
  • #: 預(yù)處理符號(hào)
運(yùn)算符重載注意事項(xiàng)
  1. 運(yùn)算重載符不可以改變語(yǔ)法結(jié)構(gòu)
  2. 運(yùn)算重載符不可以改變操作數(shù)的個(gè)數(shù)
  3. 運(yùn)算重載符不可以改變優(yōu)先級(jí)
  4. 運(yùn)算重載符不可以改變結(jié)合性
  5. 不能創(chuàng)建新的運(yùn)算符

+,- 運(yùn)算符重載

Complex operator+(const Complex& other);//+運(yùn)算符重載    成員函數(shù)實(shí)現(xiàn)
friend Complex operator-(const Complex&A, const Complex&B);//-運(yùn)算符重載 非成員函數(shù)實(shí)現(xiàn)

=賦值運(yùn)算符重載

如果沒(méi)有重載賦值運(yùn)算符,操作系統(tǒng)會(huì)有缺省運(yùn)算符重載,編譯器提供的默認(rèn)拷貝賦值操作符重載,同默認(rèn)拷貝構(gòu)造一樣,默認(rèn)拷貝賦值操作符重載同樣是淺拷貝。

Complex operator=(const Complex&other); //=運(yùn)算符重載    成員函數(shù)實(shí)現(xiàn)
注意事項(xiàng)
  1. 避免自賦值
  2. 釋放舊資源
  3. 分配新資源
  4. 拷貝新內(nèi)容
  5. 返回自引用
//為了簡(jiǎn)便,只實(shí)現(xiàn)=運(yùn)算符的避免自賦值,更多請(qǐng)看string類
Complex operator=(const Complex&other)
{
    if (&other != this) //防止自賦值
    {
        m_real = other.m_real;
        m_imaginary = other.m_imaginary;
    }
    return *this;
}

前++,后++運(yùn)算符重載

Complex operator++();       //前++運(yùn)算符重載  成員函數(shù)實(shí)現(xiàn)
Complex operator++(int);    //后++運(yùn)算符重載通過(guò)啞元實(shí)現(xiàn)    成員函數(shù)實(shí)現(xiàn)

流操作符>>,<<重載

cout是輸出類的對(duì)象,而cin是輸入類的對(duì)象,C++頭文件iostream取自istream和ostream之意

流操作符>>,<<一般使用非成員函數(shù)實(shí)現(xiàn),也就是友元函數(shù)實(shí)現(xiàn),這樣可以符合程序員的慣性思維

friend ostream &operator<<(ostream &os, const Complex&other);//IO流運(yùn)算符重載函數(shù)一般聲明為類的友元函數(shù)
friend istream &operator >> (istream &is, Complex&other);       //類的非成員函數(shù)重載>>提取運(yùn)算符

讓我們來(lái)看一下如果使用類成員方法重載流操作運(yùn)算符會(huì)怎樣一個(gè)結(jié)果

istream &operator>>(istream &is);       //類的成員函數(shù)重載>>提取運(yùn)算符

這樣定義的話使用的時(shí)候

Complex test;
test >> cin;    //類的成員函數(shù)提取運(yùn)算符的調(diào)用

跟自己使用cin不太一樣對(duì)不對(duì),就像一個(gè)反人類的設(shè)計(jì)..

運(yùn)算符重載示例程序1

//demo_2.cpp
#include<iostream>
using namespace std;
#define IS_MEMBER 0
class Complex
{
    double m_real;
    double m_imaginary;
public:
    Complex(double r = 0, double i = 0);
    void Complex_show();
    Complex operator+(const Complex& other);                    //+運(yùn)算符重載    成員函數(shù)實(shí)現(xiàn)
    Complex operator=(const Complex&other);                     //=運(yùn)算符重載    成員函數(shù)實(shí)現(xiàn)
    Complex operator++();       //前++運(yùn)算符重載  成員函數(shù)實(shí)現(xiàn)
    Complex operator++(int);    //后++運(yùn)算符重載  成員函數(shù)實(shí)現(xiàn)
    friend Complex operator-(const Complex&A, const Complex&B); //-運(yùn)算符重載    非成員函數(shù)實(shí)現(xiàn)
    friend ostream &operator<<(ostream &os, const Complex&other);//IO流運(yùn)算符重載函數(shù)一般聲明為類的友元函數(shù)
#if IS_MENBER
    istream &operator>>(istream &is);       //類的成員函數(shù)重載>>提取運(yùn)算符
#else
    friend istream &operator >> (istream &is, Complex&other);       //類的非成員函數(shù)重載>>提取運(yùn)算符
#endif
};
int main()
{
    Complex complex_1(1, 8), complex_2(2, 5), temp;
    cout << "===========+操作符重載===========" << endl;
    temp = complex_1 + complex_2;
    temp.Complex_show();
    cout << "===========流操作符重載===========" << endl;
    Complex test;
#if IS_MENBER
    test >> cin;    //類的成員函數(shù)提取運(yùn)算符的調(diào)用
#else
    cin >> test;
#endif
    complex_1 = test;
    cout << "===========-操作符重載===========" << endl;
    temp = complex_1 - complex_2;
    cout <<"temp:"<< temp << endl;
    cout << "============前++后++==========" << endl;
    Complex complex_3(1, 1);
    cout << complex_3++;
    cout << complex_3;
    cout << ++complex_3;


    cin.get();
    cin.get();
    return 0;
}

Complex::Complex(double r, double i)
{
    m_real = r;
    m_imaginary = i;
}

void Complex::Complex_show()
{
    cout << m_real << "+" << m_imaginary << "i" << endl;
}

Complex Complex::operator+(const Complex & other)
{
    Complex temp;
    temp.m_real = this->m_real + other.m_real;
    temp.m_imaginary = this->m_imaginary + other.m_imaginary;
    return temp;
}
Complex Complex::operator=(const Complex & other)
{
    if (&other != this)
    {
        m_real = other.m_real;
        m_imaginary = other.m_imaginary;
    }
    return *this;
}
Complex Complex::operator++()
{
    this->m_real = this->m_real + 1;
    return *this;
}
Complex Complex::operator++(int)
{
    Complex temp = *this;
    this->m_real = this->m_real + 1;

    return temp;
}
#if IS_MENBER
istream & Complex::operator >> (istream & is)
{
    cin >> this->m_real >> this->m_imaginary;
    // TODO: 在此處插入 return 語(yǔ)句
    return is;
}
#else
istream & operator >> (istream & is, Complex & other)
{
    is >> other.m_real >> other.m_imaginary;
    // TODO: 在此處插入 return 語(yǔ)句
    return is;
}

#endif

Complex operator-(const Complex & A, const Complex & B)
{
    Complex temp;
    temp.m_real = A.m_real - B.m_real;
    temp.m_imaginary = A.m_imaginary - B.m_imaginary;
    return temp;
}
ostream & operator<<(ostream & os, const Complex & other)
{
    os << other.m_real << "+" << other.m_imaginary << "i" << " ";
    // TODO: 在此處插入 return 語(yǔ)句
    return os;
}

//運(yùn)行結(jié)果
===========+操作符重載===========
3+13i
===========流操作符重載===========
4 5
===========-操作符重載===========
temp:2+0i
============前++后++==========
1+1i 2+1i 3+1i

new,delete重載

//類內(nèi)實(shí)現(xiàn)new運(yùn)算符重載 new的返回值必須是void* 第一個(gè)參數(shù)必須為size_t
void* operator new(size_t size);//類的非成員函數(shù)重載new
//類內(nèi)實(shí)現(xiàn)new運(yùn)算符重載 new的返回值必須是void* 第一個(gè)參數(shù)必須為void*
void  operator delete(void* ptr);//類的非成員函數(shù)重載delete

注意:對(duì)于new的重載返回值必須是void*;delete的重載返回值一定是void

運(yùn)算符重載示例程序2

//demo_3.cpp
#include<iostream>
using namespace std;
class Integer
{
    char* m_str;
    int m_len;
public:
    Integer()
    {
        m_len = 1;
        m_str = new char[m_len];
        m_str[0] = '\0';
    }
    Integer(const char* str)
    {
        m_len = strlen(str) + 1;    //這個(gè)1留給\0
        m_str = new char[m_len];
        strcpy(m_str, str);
    }
    char & operator[](int i);
    //類內(nèi)實(shí)現(xiàn)new運(yùn)算符重載 new的返回值必須是void* 第一個(gè)參數(shù)必須為size_t
    void* operator new(size_t size)
    {
        return (Integer*)malloc(size);
    }
    //類內(nèi)實(shí)現(xiàn)new運(yùn)算符重載 new的返回值必須是void* 第一個(gè)參數(shù)必須為void*
    void operator delete(void* ptr)
    {
        free(ptr);
    }
    friend ostream &operator<<(ostream &os, const Integer&other);
};

int main()
{
    Integer* arr = new Integer("hello world!");
    cout << *arr << endl;
    Integer str("hello C++!");
    for (int i = 0; i <= 10; i++)
    {
        cout << str[i];
    }
    delete arr;
    cin.get();
    return 0;
}
ostream & operator<<(ostream & os, const Integer & other)
{
    cout << other.m_str;
    // TODO: 在此處插入 return 語(yǔ)句
    return os;
}

char & Integer::operator[](int i)
{
    //TODO: 在此處插入 return 語(yǔ)句
    return m_str[i];
}

//運(yùn)行結(jié)果
hello world!
hello C++!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容