c++的一大特性就是重载(overload),通过重载可以把功能相似的几个函数合为一个,使得程序更加简洁、高效。在c++中不止函数可以重载,运算符也可以重载。由于一般数据类型间的运算符没有重载的必要,所以运算符重载主要是面向对象之间的。

1.一般运算符重载

在进行对象之间的运算时,程序会调用与运算符相对应的函数进行处理,所以运算符重载有两种方式:成员函数和友元函数。成员函数的形式比较简单,就是在类里面定义了一个与操作符相关的函数。友元函数因为没有this指针,所以形参会多一个。


  1. class A
  2. {
  3. public:
  4. A(int d):data(d){}
  5. A operator+(A&);//成员函数
  6. A operator-(A&);
  7. A operator*(A&);
  8. A operator/(A&);
  9. A operator%(A&);
  10. friend A operator+(A&,A&);//友元函数
  11. friend A operator-(A&,A&);
  12. friend A operator*(A&,A&);
  13. friend A operator/(A&,A&);
  14. friend A operator%(A&,A&);
  15. private:
  16. int data;
  17. };
  18. //成员函数的形式
  19. A A::operator+(A &a)
  20. {
  21. return A(data+a.data);
  22. }
  23. A A::operator-(A &a)
  24. {
  25. return A(data-a.data);
  26. }
  27. A A::operator*(A &a)
  28. {
  29. return A(data*a.data);
  30. }
  31. A A::operator/(A &a)
  32. {
  33. return A(data/a.data);
  34. }
  35. A A::operator%(A &a)
  36. {
  37. return A(data%a.data);
  38. }
  39. //友元函数的形式
  40. A operator+(A &a1,A &a2)
  41. {
  42. return A(a1.data+a2.data);
  43. }
  44. A operator-(A &a1,A &a2)
  45. {
  46. return A(a1.data-a2.data);
  47. }
  48. A operator*(A &a1,A &a2)
  49. {
  50. return A(a1.data*a2.data);
  51. }
  52. A operator/(A &a1,A &a2)
  53. {
  54. return A(a1.data/a2.data);
  55. }
  56. A operator%(A &a1,A &a2)
  57. {
  58. return A(a1.data%a2.data);
  59. }
  60. //然后我们就可以对类的对象进行+、-、*、/了。
  61. void main(void)
  62. {
  63. A a1(1),a2(2),a3(3);
  64. a1=a2+a3;
  65. //或者
  66. a1=a2.operator+(a3);
  67. }

注意:在进行a2+a3的时候会出错,因为我们在上面对+定义了两种方法,去掉一种即可。

2.关系运算符重载

因为函数体比较简单,后面我就只给出成员函数形式的函数声明了,关系运算符有==,!=,<,>,<=,>=。


  1. bool operator == (const A& );
  2. bool operator != (const A& );
  3. bool operator < (const A& );
  4. bool operator <= (const A& );
  5. bool operator > (const A& );
  6. bool operator >= (const A& );

3.逻辑运算符重载


  1. bool operator || (const A& );
  2. bool operator && (const A& );
  3. bool operator ! ();

4.单目运算符重载

这里的+、-是正负的意思,放在对象前面。


  1. A& operator + ();
  2. A& operator - ();
  3. A* operator & ();
  4. A& operator * ();

5.自增减运算符重载

++和–根据位置的不同有四种情况,都可以重载。


  1. A& operator ++ ();//前置++
  2. A operator ++ (int);//后置++
  3. A& operator --();//前置--
  4. A operator -- (int);//后置--

6.位运算符重载

按位操作。


  1. A operator | (const A& );
  2. A operator & (const A& );
  3. A operator ^ (const A& );
  4. A operator << (int i);
  5. A operator >> (int i);
  6. A operator ~ ();

7.赋值运算符重载

没有=哦。


  1. A& operator += (const A& );
  2. A& operator -= (const A& );
  3. A& operator *= (const A& );
  4. A& operator /= (const A& );
  5. A& operator %= (const A& );
  6. A& operator &= (const A& );
  7. A& operator |= (const A& );
  8. A& operator ^= (const A& );
  9. A& operator <<= (int i);
  10. A& operator >>= (int i);

8.内存运算符重载


  1. void *operator new(size_t size);
  2. void *operator new(size_t size, int i);
  3. void *operator new[](size_t size);
  4. void operator delete(void*p);
  5. void operator delete(void*p, int i, int j);
  6. void operator delete [](void* p);

9.特殊运算符重载

上面的运算符重载都有两种方式,而下面的运算符只能用一种,特殊吧。 这些运算符的重载只能是成员函数。


  1. A& operator = (const A& );
  2. char operator [] (int i);//返回值不能作为左值
  3. const char* operator () ();
  4. T operator -> ();
  5. //类型转换符
  6. operator char* () const;
  7. operator int ();
  8. operator const char () const;
  9. operator short int () const;
  10. operator long long () const;
  11. //还有很多就不写了

而这些只能以友元函数的形式重载


  1. friend inline ostream &operator << (ostream&, A&);//输出流
  2. friend inline istream &operator >> (istream&, A&);//输入流

10.总结

两种重载方式的比较:

  • 一般情况下,单目运算符最好重载为类的成员函数;双目运算符则最好重载为类的友元函数。
  • 以下一些双目运算符不能重载为类的友元函数:=、()、[]、->。
  • 类型转换函数只能定义为一个类的成员函数而不能定义为类的友元函数。 C++提供4个类型转换函数:reinterpret_cast(在编译期间实现转换)、const_cast(在编译期间实现转换)、stactic_cast(在编译期间实现转换)、dynamic_cast(在运行期间实现转换,并可以返回转换成功与否的标志)。
  • 若一个运算符的操作需要修改对象的状态,选择重载为成员函数较好。
  • 若运算符所需的操作数(尤其是第一个操作数)希望有隐式类型转换,则只能选用友元函数。
  • 当运算符函数是一个成员函数时,最左边的操作数(或者只有最左边的操作数)必须是运算符类的一个类对象(或者是对该类对象的引用)。如果左边的操作数必须是一个不同类的对象,或者是一个内部 类型的对象,该运算符函数必须作为一个友元函数来实现。
  • 当需要重载运算符具有可交换性时,选择重载为友元函数。

注意事项:

  1. 除了类属关系运算符”.“、成员指针运算符”.*“、作用域运算符”::“、sizeof运算符和三目运算符”?:“以外,C++中的所有运算符都可以重载。
  2. 重载运算符限制在C++语言中已有的运算符范围内的允许重载的运算符之中,不能创建新的运算符。
  3. 运算符重载实质上是函数重载,因此编译程序对运算符重载的选择,遵循函数重载的选择原则。
  4. 重载之后的运算符不能改变运算符的优先级和结合性,也不能改变运算符操作数的个数及语法结构。
  5. 运算符重载不能改变该运算符用于内部类型对象的含义。它只能和用户自定义类型的对象一起使用,或者用于用户自定义类型的对象和内部类型的对象混合使用时。
  6. 运算符重载是针对新类型数据的实际需要对原有运算符进行的适当的改造,重载的功能应当与原有功能相类似,避免没有目的地使用重载运算符。

【C/C++开发】运算符重载的更多相关文章

  1. 网易云课堂_C++开发入门到精通_章节4:运算符重载

    课时23运算符重载 运算符重载 重载赋值运算符 Person& Person::operator=(const Person& other) { //检查自赋值 if (this == ...

  2. 【C/C++开发】运算符重载二

    C++中预定义的运算符的操作对象只能是基本数据类型.但实际上,对于许多用户自定义类型(例如类),也需要类似的运算操作.这时就必须在C++中重新定义这些运算符,赋予已有运算符新的功能,使它能够用于特定类 ...

  3. swift:高级运算符(位运算符、溢出运算符、优先级和结合性、运算符重载函数)

    swift:高级运算符 http://www.cocoachina.com/ios/20140612/8794.html 除了基本操作符中所讲的运算符,Swift还有许多复杂的高级运算符,包括了C语和 ...

  4. C++之运算符重载(1)

    在前一节中曾提到过,C++中运行时的多态性主要是通过虚函数来实现的,而编译时的多态性是由函数重载和运算符重载来实现的.这一系列我将主要讲解C++中有关运算符重载方面的内容.在每一个系列讲解之前,都会有 ...

  5. [转]C++之运算符重载(1)

    在前一节中曾提到过,C++中运行时的多态性主要是通过虚函数来实现的,而编译时的多态性是由函数重载和运算符重载来实现的.这一系列我将主要讲解C++中有关运算符重载方面的内容.在每一个系列讲解之前,都会有 ...

  6. Swift教程之运算符重载

    http://blog.csdn.net/mengxiangyue/article/details/43437797 原文地址:http://www.raywenderlich.com/80818/o ...

  7. 《挑战30天C++入门极限》C++运算符重载赋值运算符

        C++运算符重载赋值运算符 自定义类的赋值运算符重载函数的作用与内置赋值运算符的作用类似,但是要要注意的是,它与拷贝构造函数与析构函数一样,要注意深拷贝浅拷贝的问题,在没有深拷贝浅拷贝的情况下 ...

  8. 为什么Java不支持运算符重载?

    另一个类似棘手的Java问题.为什么 C++ 支持运算符重载而 Java 不支持? 有人可能会说+运算符在 Java 中已被重载用于字符串连接,不要被这些论据所欺骗.与 C++ 不同,Java 不支持 ...

  9. C++ 运算符重载时,将运算符两边对象交换问题.

    在C++进行运算符重载时, 一般来讲,运算符两边的对象的顺序是不能交换的. 比如下面的例子: #include <iostream> using namespace std; class ...

随机推荐

  1. waitgroup等待退出

    等待一组协程结束,用sync.WaitGroup操作 package main import ( "fmt" "sync" "time" ) ...

  2. 洛谷 P3374 【模板】树状数组 1 & P3368 【模板】树状数组 2 题解

    一维树状数组的作用主要是单点修改,单点查询,区间修改,区间查询. 模板1是单点修改,区间查询:模板2是单点查询,区间修改. 模板1: #include<iostream> #include ...

  3. CMD browser in Linux -- Links

    Links is an open source web browser written in C programming Language. It is available for all major ...

  4. C++标准库分析总结(六)——<Map、Multimap、Set、Multiset设计原则>

    关联容器我们可以看做是一个小型的数据库,它就是用key找value,编译器底层对于关联容器的实现有两种:红黑树(Red-Block tree)和哈希表(hash table,散列表). 一.红黑树简单 ...

  5. Java 单例设计模式之 饿汉式和懒汉式

    public class InstanceSampleTest { public static void main(String[] args) { /** 单例设计模式的 饿汉式和懒汉式 * 单例模 ...

  6. 在开发iOS程序时对日期处理的总结

    小贴士(Tips)-iOS 由于iOS的设备对应多国语言,用户也可以选择不同的日历模式.比如日本的和历,泰国日历等等. 用户也可以自行设定24小时制或者12小时制来显示时间.这些设置会直接影响应用程序 ...

  7. [Andorid] 通过JNI实现kernel与app进行spi通讯

    CPU:RK3399 系统:Android 7.1 人脸识别的要求越来越高,因此主板增加了 SE 加密芯片,加密芯片通过 spi 接口与 CPU 通讯. 对于 kernel 层的代码,Linux 原始 ...

  8. createElement与createDocumentFragment的一些小区别

    在DOM操作里,createElement是创建一个新的节点,createDocumentFragment是创建一个文档片段. 网上可以搜到的大部分都是说使用createDocumentFragmen ...

  9. How does Request.IsAuthenticated work?

    How does Request.IsAuthenticated work? MSDN Code Sample Description: The following code example uses ...

  10. STM32 + RT Thread OS 串口通讯

    1.   创建项目 a)   禁用Finsh和console b)   默认情况下,项目文件包含了finsh,它使用COM1来通讯,另外,console输出(rt_kprintf)也使用了COM1.因 ...