谈C++中运算符重载及其不合理性

    xiaoxiao2021-03-25  92

    原本写这篇主要是想记录一下发现的一个冷知识:C++中运算符重载是作为类对象的成员函数,而C#中是作为类的静态成员函数。因为昨天睡觉的时候我突然想起来,C++中类里面的比较函数一般都要定义为static的,才能传到sort函数里,但是operator重载的运算符本身意义也非常符合属于类本身,而不是单个对象的这种意义,为什么就不是定义成static的呢?查了下发现C#中果然就是需要把类中的运算符重载定义成static的。结果写着写着写多了,只好顺便把C++中运算符重载的东西给总结一下。个人感觉C#的方式更合理直观一点,早就看C++的运算符重载不顺眼了。文章第二部分解释原因

    C++中运算符重载

    运算符重载为类的成员函数的原理

    类实例的成员函数,如果一个函数是成员函数,则其必包含一个隐式的this指针传进去;因此如果运算符时一个成员函数,其左侧运算符对象就绑定到隐式的this参数。即相当于运算符左侧的对象,作为调用这个运算符的实例,其this指针也传了进去。

    运算符重载的规则:

    赋值操作符(=),下标操作符([]),函数调用操作符(()),指针成员访问箭头(->)必须重载为类成员函数。和赋值操作符一样,复合赋值操作符通常定义为成员。与赋值操作符不同的是,不一定飞的这样做,如果定义为非成员,编译器不会报告错误。【复合赋值运算符指+=】改变对象状态或者与给定类型紧密联系的其他一些操作符,入自增,自减和解引用,通常定义为类成员对称的操作符,for example:算数操作符、相等操作符、关系操作符和位操作符,最好定义为非成员函数。IO操作必须定义为非成员函数,因为<<,>>的左侧是一个系统操作符,不符合成员函数的this指针调用

    至于第四条是为什么呢,《C++ Primer》(p493)里给的解释是,如果想提供含有类对象的混合表达式,运算符必须定义为非成员的函数。

    string s = "world"; string t = s + "abc"; string u = "hi" + s;

    如果+运算符定义成一个string类的成员函数的话,第三句话会报错,因为”hi”是一个const char*类型的,它根本就没有成员函数。 另外关于双

    单目运算符和双目运算符

    目和单目运算符重载的区别:

    双目运算符重载为类的成员函数时,函数只显式说明一个参数,该形参是运算符的右操作数。前置单目运算符重载为类的成员函数时,不需要显式说明参数,即函数没有形参。后置单目运算符重载为类的成员函数时,函数要带有一个整型形参。

    对于2这个问题,比如前置的++,–还有表示正负号的+和-都是这种情况。 对于3这个问题,比如后置的++和–

    关于赋值运算符的小tips

    一般重载运算符的时候,尽量保证重载之后的语义跟之前的相接近。比如重载赋值运算符的时候,就需要返回*this的引用,保证连等性质:

    a = b = c;

    C++运算符重载的不合理性

    我直觉上觉得用static来修饰运算符的重载是一件符合直觉的事情【但是因为static修饰的成员函数,里面是不含有this指针的,所以必须要像友员那样讲两个操作符都作为参数传进去】但是C++为什么不这样做呢,关于这个问题,并没有找到为什么C++不选择那样做,倒是发现C#是这样要求的,在msdn网站上有个人问了为什么C#里面运算符重载必须是static。 Eric Lippert是前C#的首席工程师,他给解释了为什么C#要选择这样做:

    他说他们设计语言特性的时候,首先要考虑到的是优点要超过其代价,在C++中不要求static,的代价太过大,有点太过小。比如这样就牺牲了对称性,比如像上面那个例子中的str+”abc”与”abc”+str,如果重载成成员函数就不行了。这样非常反直觉。通过重载成静态函数,这样能够控制传入的两边的参数。在C++中,只能再非指针类型上,定义重载运算符。而C#中还区分了引用类型和值类型。比如C++中一个比较坑的地方在于: string a = "123"; string b = "asd"; a+b = 3;

    以上的这种写法居然合理的!之前的一篇文章说过这个问题C++中const和引用修饰变量和函数的总结 因为a+b返回的是一个string类型,其是可以直接调用它的成员函数的。虽然C++后来加了限定比如用&&和&来修饰,达到限制调用类型对象左值还是右值引用的目的。 而如果在C#中,就不会有这种情况了,两目运算符的两边都要传进去。

    参考资料

    Why are overloaded operators always static in C#?

    转载请注明原文地址: https://ju.6miu.com/read-13745.html

    最新回复(0)