• C++中的运算符重载


    首先思考以下几个问题:

    1.什么是运算符重载?

    2.为什么要重载运算符,它有什么用?

    3.可以重载哪些运算符?

    4.重载运算符有哪些规则?

    一、基本概念

    我们在程序中使用各种操作符,比如加(+)、赋值(=)等等。运算符重载可以重新赋予操作符的含义,举个栗子,对于加号操作符,一般都是将两个数进行相加,而不能将两个自定义类的对象相加,但是通过运算符重载可以这么做。

    重载运算符是具有特殊名称的函数,函数具有哪些特征呢?1.函数名称;2.返回类型;3.参数列表;4.函数体。

    1.名称的写法是保留字operator后接需定义的操作符号;

    2.返回类型后面再说;

    3.参数:参数数目与该运算符作用的运算对象数目相同,但如果是作为一个类的成员函数,(显式)参数数目比运算对象总数少一个(因为有一个隐含的this形参)。

    1.哪些运算符可以被重载

    只知道哪些可以、哪些不可以被重载,没有太大意义。

    2.重载运算符怎么调用

    如果是非成员运算符函数:

    star1 + star2;			//普通表达式
    operator+(star1, star2);	//等价的函数调用

    如果是成员运算符函数:

    star1 += star2;			//基于调用的表达式
    star1.operator+=(star2);	//等价的调用
    

      

    二、为什么要重载运算符

    大多数人平时很少用到运算符重载,因为运算符重载的功能一般都可以通过直接写一个普通函数实现。但运算符重载可以使的程序更加“优美”,在有的情形下,可以使我们更容易使用标准库容器和算法。

    三、输入、输出运算符

    我们现在有一个类SuperStar,代表超级巨星,它有一个成员变量代表巨星的姓名。

    现在我们的任务是输入、输出巨星的名字。

    class SuperStar
    {
    public:
    	SuperStar();
    	~SuperStar();
    private:
    	string m_strName;		//姓名
    };

    1.输出运算符<<

    输出运算符第一个参数是ostream的引用,第二个参数是一个常量的引用。

    ostream &operator<<(ostream &os, const SuperStar &star)
    {
    	os << star.m_strName;
    	return os;
    }

    2.输入运算符>>

    输入运算符第一个参数是将要读取的流的引用,第二个参数是将要读入到的对象的引用。

    istream &operator>>(istream &is, SuperStar &star)
    {
    	if (is)//检查是否输入成功
    		is >> star.m_strName;
    	else
    		star = SuperStar();
    	return is;
    }

    值得注意的是参数为什么是引用,还有参数为什么是/不是常量。

    输入输出运算符必须是非成员函数,但是IO运算符需要读写类的非公有成员,所以一般被声明为友元。

    friend istream& operator>>(istream &, SuperStar &);
    friend ostream& operator<<(ostream &, const SuperStar &);
    

      

    四、算术和关系运算符

    1.相等运算符==

    假如现在有2个明星,一个叫饭冰冰,另一个叫凤咀

     VS 

    我们根据名字来判断她们是不是一样的(这样做也许有失合理,请不要太在意细节)

    bool operator==(const SuperStar &star1, const SuperStar &star2)
    {
    	return star1.m_strName == star2.m_strName;
    }
    
    bool operator!=(const SuperStar &star1, const SuperStar &star2)
    {
    	return !(star1 == star2);
    }

    让我们试一下效果:

    SuperStar star1;
    SuperStar star2;
    cout << "亲爱的经纪人,请创造1号女星:";
    cin >> star1;
    cout << "请创造2号女星:";
    cin >> star2;
    cout << "1号" << star1 << ";2号" << star2 << endl;;
    cout << "她们" << ((star1 == star2) ? "相同" : "不相同") << endl;

    2.算术运算符+

    SuperStar operator+(const SuperStar &star1, const SuperStar &star2)
    {
    	SuperStar star3 = star1;
    	star3 += star2;
    	return star3;
    }

    上面使用了复合赋值运算符+=,这一点后面会将。(note:如果类同时定义了算术运算符和复合赋值运算符,通常应使用复合赋值运算符来实现算术运算符)

    五、赋值运算符

    1.赋值运算符=

    凤咀对自己名字不满意,于是想改名叫饭冰冰。

    :“我叫饭冰冰,你爱我吗?”

    SuperStar & SuperStar::operator=(const SuperStar &star)
    {
    	if (this != &star)
    	{
    		m_strName = star.m_strName;
    	}
    	return *this;
    }

    这里要注意赋值给自己的情况,有一本叫《C++沉思录》的书里面有深入的讲解。

    赋值运算符必须定义为成员函数。

    2.复合赋值运算符+=

    凤咀想:直接叫别人的名字不太好,把她名字加在我后面吧!

    :“我叫凤咀饭冰冰,你还爱我吗?”

    SuperStar & SuperStar::operator+=(const SuperStar &star)
    {
    	m_strName += star.m_strName;
    	return *this;
    }

    复合赋值运算符不非得是类的成员,不过倾向于把所有赋值运算都定义在类内部。

    六、递增和递减运算符

    1.前置递增/递减运算符

    首先在类中定义它们:

    SuperStar &operator++();
    SuperStar &operator--();

    具体实现:

    SuperStar & SuperStar::operator++()
    {
    	check();
    	++curr;
    	return *this;
    }
    SuperStar & SuperStar::operator--()
    {
    	--curr;
    	check();
    	return *this;
    }

    注意其中检查是否越界,如果越界,将会抛出out_of_range异常。

    2.后置递增/递减运算符

    为了区分前置与后置,后置版本接受一个额外的(不使用的)int类型的参数。

    SuperStar & SuperStar::operator++(int)
    {
    	SuperStar ret = *this;
    	++*this;
    	return ret;
    }
    SuperStar & SuperStar::operator--(int)
    {
    	SuperStar ret = *this;
    	--*this;
    	return ret;
    }

    后置运算符调用各自的前置版本来完成实际的工作。

    以上只是运算符重载的一小部分,想认识更多还需要多看书多思考。

  • 相关阅读:
    五子棋人机对战设计
    通过getSystemServices获取手机管理大全
    C#常见错误解决方法
    🍖数据增删改查页面搭建
    🍖django ORM 表关系与django 请求生命周期流程图
    🍖django ORM 简介
    🍖Python与django连接数据库
    🍖静态文件配置与request对象
    开启进程的两种方式
    进程PID 与PPID
  • 原文地址:https://www.cnblogs.com/hellovenus/p/6260210.html
Copyright © 2020-2023  润新知