Aq系列C++——运算符重载 2.0

博客示例源代码

  • 重载前++和后++
#include <iostream>
#include <string>
#include <algorithm>

using namespace std;

class Complex 
{
public:
    Complex(int x, int y) : _x(x), _y(y) {}
    
    void dis() 
    {
        cout << "(" << _x << "," << _y << ")" << endl;
    }

#if 0

    const Complex& operator++(void) 
    {  
        // 前++
        _x++;
        _y++;
        
        return *this;
    }

    const Complex operator++(float) 
    {  
        // 后++引入哑元
        Complex t = *this;
        
        this->_x++;
        this->_y++;
    
        return t;
    }

#endif

    friend Complex& operator++(Complex& a);  // 前++
    friend const Complex operator++(Complex& a, int);  // 后++
    
private:

    int _x;
    int _y;
};

Complex& operator++(Complex& a) 
{  
    // 友元函数必须传引用
    a._x++;
    a._y++;

    return a;
}

const Complex operator++(Complex& a, int) 
{
    Complex c = a;
    
    a._x++;
    a._y++;

    return c;
}

int main()
{
    int x;
    //x ++++;
    cout << "------------" << endl;
    ++++ x;
    
    Complex a1(3, 4);
    Complex a2(3, 4);

    Complex c1 = ++++ a1;
    a1.dis();
    c1.dis();

    Complex c2 = a2 ++;
    a2.dis();
    c2.dis();

    return 0;
}

一定要注意,i ++++ i的区别,这里可以试一下i ++++++++ i,我们可以得到i ++++是不对的,原因是——

我们在实现后 ++ 的函数的时候,返回值的类型是const,这样子导致i ++后已经是一个const对象,如果再对这个const对象进行++操作,就会CE。我们通常使用引用&是为了节省空间,不会再更多地申请新的内存空间(如果是return by value就会比较浪费空间,因为我们已经可以保证它是const不变的了)。

  • 流输入输出运算符重载
#include <iostream>
#include <string>
#include <algorithm>

using namespace std;

class Complex 
{
public:
    Complex(int x, int y) : _x(x), _y(y) {}
    
    void dis() 
    {
        cout << "(" << _x << "," << _y << ")" << endl;
    }
    
#if 0

    Complex& operator++(void) 
    {  
        // 前++
        _x++;
        _y++;
        return *this;
    }

    const Complex operator++(int) 
    {  
        // 后++引入哑元
        Complex t = *this;
         
        this->_x++;
        this->_y++;
    
        return t;
    }

    friend Complex& operator++(Complex& a);             // 前++
    friend const Complex operator++(Complex& a, int);   // 后++
    
#endif

    friend ostream& operator<<(ostream& os, const Complex& c);
    friend istream& operator>>(istream& is, Complex& c);
    
private:

    int _x;
    int _y;
};

ostream& operator<<(ostream& os, const Complex& c)
{
    os << "(" << c._x << ", " << c._y << ")" << endl;
    return os;
}

istream& operator>>(istream& is, Complex& c)
{
    is >> c._x >> c._y;
    return is;
}

int main()
{
    Complex a1(3, 4);
    Complex a2(3, 4);

    cout << a1 << endl;
    
    cin >> a2;
    cout << a2 << endl;
    
    
    return 0;
}

流操作符只能用友元实现,不能用类成员函数,因为iostream是库函数。

  • 友元还是类成员变量
#include <iostream>
#include <string>

using namespace std;

//Sender sender; Mail mail;
//sender << mail; Sender的类成员函数, Mail的友元

class Mail;
class Sender 
{
public:
    Sender(string s) : _addr(s) {}
    Sender& operator<<(const Mail& maill);      // 成员 
    
    // friend Sender& operator<<(Sender& sender, Mail& maill);
    
private:
    string _addr;
};

class Mail 
{
public:
    Mail(string title, string content) :_title(title), _content(content) {}
    
    // friend Sender& operator<<(Sender& sender, Mail& maill);
    
    friend Sender& Sender::operator<<(const Mail & mail);
    
private:
    string _title;
    string _content;
};

Sender& Sender::operator<<(const Mail & mail)
{
    cout << "Address:" << _addr << endl;
    cout << "Title :" << mail._title << endl;
    cout << "Content:" << mail._content << endl;
    
    return *this;
}

// #if 0

// 方式2
// Sender& operator<<(Sender& sender, Mail& mail) 
// {
//     cout << "Address:" << sender._addr << endl;
//     cout << "Title :" << mail._title << endl;
//     cout << "Content:" << mail._content << endl;
    
//     return sender;
// }

// #endif

int main() 
{
    Sender sender("11111@163.com");
    
    Mail mail("note", "meeting at 3:00 pm");
    Mail mail2("tour", "One night in beijing");
    
    sender << mail << mail2;
    
    return 0;
}

这个相当于是上面流操作符重载的说明


  • 类型转换
#include <iostream>
#include <string>

using namespace std;

class Point3D;

class Point2D 
{
public:

    Point2D(int x, int y) :_x(x), _y(y) {}

    void dis()
    {
        cout << "(" << _x << "," << _y << ")" << endl;
    }

    friend Point3D; // 友元类, 可以访问Point2D的私有成员变量
    
private:

    int _x;
    int _y;
};

class Point3D
{
public:

    Point3D(int x, int y, int z) : _x(x), _y(y), _z(z) {}
    
    explicit Point3D(Point2D &p)
    {
        cout << "调用构造函数" << endl;
        
        this->_x = p._x;
        this->_y = p._y;
        this->_z = 0;
    }
    
    void dis()
    {
        cout << "(" << _x << "," << _y << "," << _z << ")" << endl;
    }
    
private:

    int _x;
    int _y;
    int _z;
};


int main() 
{
    Point2D p2(1, 2);
    p2.dis();

    Point3D p3(3, 4, 5);
    p3.dis();


    Point3D p3a = p2;   //使用explicit后不会隐式的进行类型转换;
    
    // Point3D p3a = Point3D(p2);  // 一个显式的转换
    p3a.dis();

    return 0;
}

这里就是学了下explicit

  • 用类型转换操作符函数进行转换
#include <iostream>
#include <string>

using namespace std;

class Point3D;

class Point2D 
{
public:
    Point2D(int x, int y) :_x(x), _y(y) {}

    void dis()
    {
        cout << "(" << _x << "," << _y << ")" << endl;
    }

    operator Point3D();

    friend Point3D; // 友元类, 可以访问Point2D的私有成员变量
    
private:
    int _x;
    int _y;
};

class Point3D
{
public:
    Point3D(int x, int y, int z) : _x(x), _y(y), _z(z) {}

// #if 0

//     explicit Point3D(Point2D &p)
//     {
//         cout << "调用构造函数" << endl;
        
//         this->_x = p._x;
//         this->_y = p._y;
//         this->_z = 0;
//     }
    
// #endif
    
    void dis()
    {
        cout << "(" << _x << "," << _y << "," << _z << ")" << endl;
    }
    
private:

    int _x;
    int _y;
    int _z;
};

Point2D::operator Point3D() 
{
    return Point3D(_x, _y, 123);
}

int main() 
{
    Point2D p2(1, 2);
    p2.dis();

    Point3D p3(3, 4, 5);
    p3.dis();


    // Point3D p3a = p2;   //使用explicit后不会隐式的进行类型转换;
    Point3D p3a = p2;  //一个显式的转换
    p3a.dis();

    return 0;
}

这里没有用explicit,而是重载了一下operator函数。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,928评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,192评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,468评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,186评论 1 286
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,295评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,374评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,403评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,186评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,610评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,906评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,075评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,755评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,393评论 3 320
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,079评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,313评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,934评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,963评论 2 351