一种直觉的表达,C++运算符重载

    技术2022-05-19  21

    运算符重载是C+ + 的重要组成部分,它可以让程序更加的简单易懂,简单的运算符使用可以使复杂函数的理解更直观。 对于普通对象来说我们很自然的会频繁使用算数运算符让他们参与计算,但是对于自定义类的对象来说呢?让我们看一对例程。 例程1: class Test; int main() { Test a, c; c.add (a); c.add (a); } 例程2: int main() { Test a, c; c = a + a; } 您更喜欢哪一种语法表达方式呢? 例程2是一种直觉的表达,更接近于人类所熟悉的世界,我们是无论如何也不应阻止程序员写出类似的程序来。 运算符重载允许您为类的使用者提供一个直觉的接口。通过重载类上的标准运算符,您可以发掘类的使用者的直觉。使得用户程序所用的语言是面向问题的,而不是面向机器的。最终目标是降低学习曲线并减少错误率。 有些人不喜欢operator 关键字或类体内的有些古怪的语法。考虑一下如下的例子: class Array { public: int& operator[] (unsigned i); ... }; inline int& Array::operator[] (unsigned i) { ... } 但是运算符重载语法不是被期望用来使得类的开发者的工作更简易,它被期望用来使得类的使用者的工作更简易: int main() { Test a, c; c = a + a; } 这里有一些运算符重载的实例: myString + yourString; // 可以连接两个 std::string 对象

    myDate+ +; // 可以增加一个 Date 对象

    a * b; // 可以将两个 Number 对象相乘

    a[i]; // 可以访问 Array 对象的某个元素

    x = *p; // 可以反引用一个实际"指向"一个磁盘记录的 "smart pointer" ——它实际上在磁盘上定位到 p 所指向的记录并返回给x。 当一种语言允许运算符在某种情况下被隐式调用时,运算符重载将不只提供写法上的方便。 int main() { Test a (100); Test c = a + a; cout << c; return 0; } 执行运算符重载函数返回引用将不产生临时变量,外部的Test c=a+a; 将获得一个局部的,栈空间内存地址位置上的值,而栈空间的特性告诉我们,当函数退出的时候函数体中局部对象的生命周期随之结束,所以保存在该地址中的数据也将消失,当c 对象去获取存储在这个地址中的值的时候,里面的数据已经不存在,导致c 获得的是一个随机值,所以作为双目运算的加运算符重载函数是不益采用返回引用方式编写的,当然如果一定要返回引用,我们可以在堆内存中动态开辟空间存储数据,但是这么做会导致额外的系统开销,同时也会让程序更难读懂。 对于递增运算符来说,它的意义在于能够改变自身,返回引用的函数是可以作为左值参与运算的,所以作为单目运算符,重载它的函数采用返回引用的方式编写是最合适的。 Test operator + +() { return this->a+ +; } 一个我在实际项目中使用的例程,PACE 中的Time_Value 中使用的运算符重载: class PACE_Time_Value { public: ...... // Operator overloading. double operator - (PACE_Time_Value &tv); ...... }; double PACE_Time_Value::operator - ( PACE_Time_Value &tv) { // 取得时间差ms. double ms = (this->get_sec () - tv.get_sec ()) * 1000.0 + (this->get_usec () - tv.get_usec ()) / 1000.0; return ms; } 类的使用者调用的代码片断: ... PACE_Time_Value start_time (sec, usec); PACE_Time_Value end_time; double rtt = end_time - start_time; ... 运算符重载由于使程序设计者能够根据运算符类型的不同来决定运算符功能的不同而受到批评。因为运算符重载允许程序设计者改变运算符通常的语义,慎重使用运算符重载通常被认为是一个好习惯。 十分遗憾,Java 这门摘得编程届桂冠的语言不支持运算符重载。 除非注明,景天博客 文章均为原创。


    最新回复(0)