【C++】 运算符重载

青旅半醒 2022-06-04 08:09 370阅读 0赞

1、一元运算符

运算符重载是C++的一大特色,以函数重载的形式出现,函数名为关键字operator后跟着一个运算符,这些函数可以作为类的成员函数实现,也可以作为类的友元函数以全局函数的形式实现,而有的操作符只能以其中一种方式实现,因为全局函数没有this指针,所以在参数列表中比成员函数多一个参数。可以重载的一元运算符包括+-~&!++--,例子如下。

  1. // Overloading Unary Operators
  2. // Non-member functions
  3. class Integer {
  4. long i;
  5. Integer* This() { return this; }
  6. public:
  7. Integer(long ll = 0) : i(ll) {}
  8. // No side effects takes const& arguments
  9. friend const Integer& operator+(const Integer& a);
  10. friend const Integer operator-(const Integer& a);
  11. friend const Integer operator~(const Integer& a);
  12. friend Integer* operator&(Integer& a);
  13. friend int operator!(const Integer& a);
  14. // Side effects have non-const& argument
  15. // Prefix
  16. friend const Integer& operator++(Integer& a);
  17. // Postfix
  18. friend const Integer operator++(Integer& a, int);
  19. // Prefix
  20. friend const Integer& operator--(Integer& a);
  21. // Postfix
  22. friend const Integer operator--(Integer& a, int);
  23. };
  24. // Global operators
  25. const Integer& operator+(const Integer& a) {
  26. return a; // Unary + has no effect
  27. }
  28. const Integer operator-(const Integer& a) {
  29. return Integer(-a.i);
  30. }
  31. const Integer operator~(const Integer& a) {
  32. return Integer(~a.i);
  33. }
  34. Integer* operator&(Integer& a) {
  35. return a.This(); // &a is recursive!
  36. }
  37. int operator!(const Integer& a) {
  38. return !a.i;
  39. }
  40. // Prefix; return incremented value
  41. const Integer& operator++(Integer& a) {
  42. a.i++;
  43. return a;
  44. }
  45. // Postfix; return the value before increment:
  46. const Integer operator++(Integer& a, int) {
  47. Integer before(a.i);
  48. a.i++;
  49. return before;
  50. }
  51. // Prefix; return decremented value
  52. const Integer& operator--(Integer& a) {
  53. a.i--;
  54. return a;
  55. }
  56. // Postfix; return the value before decrement:
  57. const Integer operator--(Integer& a, int) {
  58. Integer before(a.i);
  59. a.i--;
  60. return before;
  61. }
  62. // Member functions (implicit "this")
  63. class Byte {
  64. unsigned char b;
  65. public:
  66. Byte(unsigned char bb = 0) : b(bb) {}
  67. // No side effects: const member function
  68. const Byte& operator+() const {
  69. return *this;
  70. }
  71. const Byte operator-() const {
  72. return Byte(-b);
  73. }
  74. const Byte operator~() const {
  75. return Byte(~b);
  76. }
  77. Byte operator!() const {
  78. return Byte(!b);
  79. }
  80. Byte* operator&() {
  81. return this;
  82. }
  83. // Side effects: non-const member function
  84. const Byte& operator++() { // Prefix
  85. b++;
  86. return *this;
  87. }
  88. const Byte operator++(int) { // Postfix
  89. Byte before(b);
  90. b++;
  91. return before;
  92. }
  93. const Byte& operator--() { // Prefix
  94. b--;
  95. return *this;
  96. }
  97. const Byte operator--(int) { // Postfix
  98. Byte before(b);
  99. b--;
  100. return before;
  101. }
  102. };

2、二元运算符

可以重载的二元运算符包括+-*/%^&|<<>>+=-=*=/=%=^=&=|=<<=>>=,例子如下。二元运算符一般使用非成员函数。

  1. // Overloading Binary Operators
  2. // Non-member overloaded operators
  3. // Non-member functions
  4. class Integer {
  5. long i;
  6. public:
  7. Integer(long ll = 0) : i(ll) {}
  8. // Operators that create new, modified value
  9. friend const Integer operator+(const Integer& left, const Integer& right);
  10. friend const Integer operator-(const Integer& left, const Integer& right);
  11. friend const Integer operator*(const Integer& left, const Integer& right);
  12. friend const Integer operator/(const Integer& left, const Integer& right);
  13. friend const Integer operator%(const Integer& left, const Integer& right);
  14. friend const Integer operator^(const Integer& left, const Integer& right);
  15. friend const Integer operator&(const Integer& left, const Integer& right);
  16. friend const Integer operator|(const Integer& left, const Integer& right);
  17. friend const Integer operator<<(const Integer& left, const Integer& right);
  18. friend const Integer operator>>(const Integer& left, const Integer& right);
  19. // Assignments modify & return lvalue
  20. friend Integer& operator+=(Integer& left, const Integer& right);
  21. friend Integer& operator-=(Integer& left, const Integer& right);
  22. friend Integer& operator*=(Integer& left, const Integer& right);
  23. friend Integer& operator/=(Integer& left, const Integer& right);
  24. friend Integer& operator%=(Integer& left, const Integer& right);
  25. friend Integer& operator^=(Integer& left, const Integer& right);
  26. friend Integer& operator&=(Integer& left, const Integer& right);
  27. friend Integer& operator|=(Integer& left, const Integer& right);
  28. friend Integer& operator<<=(Integer& left, const Integer& right);
  29. friend Integer& operator>>=(Integer& left, const Integer& right);
  30. // Conditional operators return true/false
  31. friend int operator==(const Integer& left, const Integer& right);
  32. friend int operator!=(const Integer& left, const Integer& right);
  33. friend int operator<(const Integer& left, const Integer& right);
  34. friend int operator>(const Integer& left, const Integer& right);
  35. friend int operator<=(const Integer& left, const Integer& right);
  36. friend int operator>=(const Integer& left, const Integer& right);
  37. friend int operator&&(const Integer& left, const Integer& right);
  38. friend int operator||(const Integer& left, const Integer& right);
  39. };
  40. // Implementation of overloaded operators
  41. const Integer operator+(const Integer& left, const Integer& right) {
  42. // Integer tmp(left.i + right.i); // 调用构造函数创建tmp对象
  43. // return tmp; // 调用拷贝构造函数把tmp拷贝到外部返回值的存储单元 调用析构函数销毁tmp对象
  44. return Integer(left.i + right.i); // 返回值优化 返回临时对象告诉编译器直接把这个对象创建在外部返回值的存储单元里
  45. }
  46. const Integer operator-(const Integer& left, const Integer& right) {
  47. return Integer(left.i - right.i);
  48. }
  49. const Integer operator*(const Integer& left, const Integer& right) {
  50. return Integer(left.i * right.i);
  51. }
  52. const Integer operator/(const Integer& left, const Integer& right) {
  53. return Integer(left.i / right.i); // right.i != 0
  54. }
  55. const Integer operator%(const Integer& left, const Integer& right) {
  56. return Integer(left.i % right.i); // right.i != 0
  57. }
  58. const Integer operator^(const Integer& left, const Integer& right) {
  59. return Integer(left.i ^ right.i);
  60. }
  61. const Integer operator&(const Integer& left, const Integer& right) {
  62. return Integer(left.i & right.i);
  63. }
  64. const Integer operator|(const Integer& left, const Integer& right) {
  65. return Integer(left.i | right.i);
  66. }
  67. const Integer operator<<(const Integer& left, const Integer& right) {
  68. return Integer(left.i << right.i);
  69. }
  70. const Integer operator>>(const Integer& left, const Integer& right) {
  71. return Integer(left.i >> right.i);
  72. }
  73. // Assignments modify & return lvalue
  74. Integer& operator+=(Integer& left, const Integer& right) {
  75. if(&left == &right) {
  76. /* self-assignment*/}
  77. left.i += right.i;
  78. return left;
  79. }
  80. Integer& operator-=(Integer& left, const Integer& right) {
  81. if(&left == &right) {
  82. /* self-assignment*/}
  83. left.i -= right.i;
  84. return left;
  85. }
  86. Integer& operator*=(Integer& left, const Integer& right) {
  87. if(&left == &right) {
  88. /* self-assignment*/}
  89. left.i *= right.i;
  90. return left;
  91. }
  92. Integer& operator/=(Integer& left, const Integer& right) {
  93. // right.i != 0
  94. if(&left == &right) {
  95. /* self-assignment*/}
  96. left.i /= right.i;
  97. return left;
  98. }
  99. Integer& operator%=(Integer& left, const Integer& right) {
  100. // right.i != 0
  101. if(&left == &right) {
  102. /* self-assignment*/}
  103. left.i %= right.i;
  104. return left;
  105. }
  106. Integer& operator^=(Integer& left, const Integer& right) {
  107. if(&left == &right) {
  108. /* self-assignment*/}
  109. left.i ^= right.i;
  110. return left;
  111. }
  112. Integer& operator&=(Integer& left, const Integer& right) {
  113. if(&left == &right) {
  114. /* self-assignment*/}
  115. left.i &= right.i;
  116. return left;
  117. }
  118. Integer& operator|=(Integer& left, const Integer& right) {
  119. if(&left == &right) {
  120. /* self-assignment*/}
  121. left.i |= right.i;
  122. return left;
  123. }
  124. Integer& operator<<=(Integer& left, const Integer& right) {
  125. if(&left == &right) {
  126. /* self-assignment*/}
  127. left.i <<= right.i;
  128. return left;
  129. }
  130. Integer& operator>>=(Integer& left, const Integer& right) {
  131. if(&left == &right) {
  132. /* self-assignment*/}
  133. left.i >>= right.i;
  134. return left;
  135. }
  136. // Conditional operators return true/false
  137. int operator==(const Integer& left, const Integer& right) {
  138. return left.i == right.i;
  139. }
  140. int operator!=(const Integer& left, const Integer& right) {
  141. return left.i != right.i;
  142. }
  143. int operator<(const Integer& left, const Integer& right) {
  144. return left.i < right.i;
  145. }
  146. int operator>(const Integer& left, const Integer& right) {
  147. return left.i > right.i;
  148. }
  149. int operator<=(const Integer& left, const Integer& right) {
  150. return left.i <= right.i;
  151. }
  152. int operator>=(const Integer& left, const Integer& right) {
  153. return left.i >= right.i;
  154. }
  155. int operator&&(const Integer& left, const Integer& right) {
  156. return left.i && right.i;
  157. }
  158. int operator||(const Integer& left, const Integer& right) {
  159. return left.i || right.i;
  160. }
  161. // Member overloaded operators
  162. // Member functions (implicit "this")
  163. class Byte {
  164. unsigned char b;
  165. public:
  166. Byte(unsigned char bb = 0) : b(bb) {}
  167. const Byte operator+(const Byte& right) const {
  168. return Byte(b + right.b);
  169. }
  170. const Byte operator-(const Byte& right) const {
  171. return Byte(b - right.b);
  172. }
  173. const Byte operator*(const Byte& right) const {
  174. return Byte(b * right.b);
  175. }
  176. const Byte operator/(const Byte& right) const {
  177. return Byte(b / right.b); // right.b != 0
  178. }
  179. const Byte operator%(const Byte& right) const {
  180. return Byte(b % right.b); // right.b != 0
  181. }
  182. const Byte operator^(const Byte& right) const {
  183. return Byte(b ^ right.b);
  184. }
  185. const Byte operator&(const Byte& right) const {
  186. return Byte(b & right.b);
  187. }
  188. const Byte operator|(const Byte& right) const {
  189. return Byte(b | right.b);
  190. }
  191. const Byte operator<<(const Byte& right) const {
  192. return Byte(b << right.b);
  193. }
  194. const Byte operator>>(const Byte& right) const {
  195. return Byte(b >> right.b);
  196. }
  197. // Assignments modify & return lvalue.
  198. // operator= can only be a member function
  199. Byte& operator=(const Byte& right) {
  200. // Handle self-assignment
  201. if(this == &right) return *this;
  202. b = right.b;
  203. return *this;
  204. }
  205. Byte& operator+=(const Byte& right) {
  206. if(this == &right) {
  207. /* self-assignment */}
  208. b += right.b;
  209. return *this;
  210. }
  211. Byte& operator-=(const Byte& right) {
  212. if(this == &right) {
  213. /* self-assignment */}
  214. b -= right.b;
  215. return *this;
  216. }
  217. Byte& operator*=(const Byte& right) {
  218. if(this == &right) {
  219. /* self-assignment */}
  220. b *= right.b;
  221. return *this;
  222. }
  223. Byte& operator/=(const Byte& right) {
  224. if(this == &right) {
  225. /* self-assignment */}
  226. b /= right.b; // right.b != 0
  227. return *this;
  228. }
  229. Byte& operator%=(const Byte& right) {
  230. if(this == &right) {
  231. /* self-assignment */}
  232. b %= right.b; // right.b != 0
  233. return *this;
  234. }
  235. Byte& operator^=(const Byte& right) {
  236. if(this == &right) {
  237. /* self-assignment */}
  238. b ^= right.b;
  239. return *this;
  240. }
  241. Byte& operator&=(const Byte& right) {
  242. if(this == &right) {
  243. /* self-assignment */}
  244. b &= right.b;
  245. return *this;
  246. }
  247. Byte& operator|=(const Byte& right) {
  248. if(this == &right) {
  249. /* self-assignment */}
  250. b |= right.b;
  251. return *this;
  252. }
  253. Byte& operator<<=(const Byte& right) {
  254. if(this == &right) {
  255. /* self-assignment */}
  256. b <<= right.b;
  257. return *this;
  258. }
  259. Byte& operator>>=(const Byte& right) {
  260. if(this == &right) {
  261. /* self-assignment */}
  262. b >>= right.b;
  263. return *this;
  264. }
  265. // Conditional operators return true/false:
  266. int operator==(const Byte& right) const {
  267. return b == right.b;
  268. }
  269. int operator!=(const Byte& right) const {
  270. return b != right.b;
  271. }
  272. int operator<(const Byte& right) const {
  273. return b < right.b;
  274. }
  275. int operator>(const Byte& right) const {
  276. return b > right.b;
  277. }
  278. int operator<=(const Byte& right) const {
  279. return b <= right.b;
  280. }
  281. int operator>=(const Byte& right) const {
  282. return b >= right.b;
  283. }
  284. int operator&&(const Byte& right) const {
  285. return b && right.b;
  286. }
  287. int operator||(const Byte& right) const {
  288. return b || right.b;
  289. }
  290. };

3、下标运算符

下标运算符[],行为像数组一样,必须是成员函数,只接受一个参数。

  1. class ByteArray
  2. {
  3. public:
  4. char operator[](int i) const;
  5. };

4、new和delete

运算符new和delete也可以进行重载,全局函数或者成员函数,用于控制动态存储分配,不过一般不这么做。

  1. void* operator new(std::size_t)
  2. void* operator new[](std::size_t);
  3. void operator delete(void*);
  4. void operator delete[](void*);
  5. inline void* operator new(std::size_t, void *p) { return p; }
  6. inline void* operator new[](std::size_t, void *p) { return p; }
  7. inline void operator delete(void*, void*) {}
  8. inline void operator delete[](void*, void*) {}

5、逗号

当逗号出现在一个对象左右,而该对象的类型是逗号定义所支持的类型时,将调用逗号运算符,然后,调用的目标不是函数参数表,而是被逗号分隔开的、没有被括号括起来的对象,除了使语言保持一致性外,这个运算符似乎没有许多实际用途。

  1. class After {
  2. pubic:
  3. const After& operator,(const After&) const { return *this; }
  4. };
  5. class Before { };
  6. Before& operator,(int, Before &b) { return b; }
  7. void test()
  8. {
  9. After a, b;
  10. a, b; // operator, called
  11. Before c;
  12. 1, c; // operator, called
  13. }

6、指针

下面是几个特殊的可重载运算符。当希望一个对象表现的像一个指针时,通常就要用到指针间接引用运算符operator->,它是个成员函数,由于这样一个对象比一般的指针有着更多与生俱来的灵巧性,于是常被称作为灵巧指针。

  1. class Object {};
  2. class ObjectContainer
  3. {
  4. public:
  5. vector<Object*> objs;
  6. };
  7. class SmatrPointer
  8. {
  9. pubic:
  10. Object* operator->() const { return oc.objs[index]; }
  11. private:
  12. ObjectContainer &oc;
  13. int index;
  14. };

另外,运算符operator->*用于成员指针;operator()是个多功能函数,参数不受限制,可以实现任意特定的功能;括号运算符进行类型转换时格式为operator Type(),它们都是成员函数。在类型转换中,有时会通过构造函数自动进行类型转换,这可能会有问题,解决方法是在构造函数前面使用explicit关键字。

  1. class Dog()
  2. {
  3. public:
  4. int run(int i) const { return i; }
  5. typedef int (Dog::*PMF)(int) const;
  6. class FuncObj
  7. {
  8. public:
  9. FuncObj(Dog *dog, PMF pmf) : ptr(dog), pmem(pmf) {}
  10. int operator()(int i) const { return (ptr->*pmem)(i); }
  11. private:
  12. Dog *ptr;
  13. PMF pmem;
  14. };
  15. FuncObj operator->*(PMF pmf)
  16. {
  17. return FuncObj(this, pmf);
  18. }
  19. }
  20. void test()
  21. {
  22. Dog d;
  23. Dog::PMF pmf = &Dog::run;
  24. (d->*pmf)(1);
  25. }
  26. Class A()
  27. {
  28. public:
  29. A(B* bb) : b(bb) {}
  30. private:
  31. B* b;
  32. };
  33. Class B()
  34. {
  35. public:
  36. operator A() const { return A(this); } // B转换为A
  37. };

7、输入输出

输入输出运算符operator>>operator<<作为全局函数,可以自定义任何想要的结果。

  1. class Integer
  2. {
  3. friend ostream& operator<<(ostream& os, const Integer &r);
  4. friend istream& operator>>(istream& is, Inteter &r);
  5. int num;
  6. };
  7. ostream& operator<<(ostream& os, const Integer &r)
  8. {
  9. os << r.num;
  10. os << endl;
  11. return os;
  12. }
  13. istream& operator>>(istream& is, Inteter &r)
  14. {
  15. is >> r.num;
  16. return is;
  17. }

8、不能重载的运算符

在可用的运算符集合里,存在一些不能重载的运算符,如下。

  1. operator.
  2. operator.*
  3. user custom operator

发表评论

表情:
评论列表 (有 0 条评论,370人围观)

还没有评论,来说两句吧...

相关阅读

    相关 c++ 运算符重载

    1. 运算符重载介绍 之前的函数重载,允许多个同名不同参数类型的函数; 运算符重载允许程序员如何使用运算符(如+、-、==、=和!)来处理不同类型的数据类型; 对于基本数

    相关 c++运算符重载

    C++不允许把下标运算符函数作为外部函数来定义,它只能是非静态的成员函数。 注意操作符重载作为友元函数和成员函数的区别 // person.cpp : 定

    相关 c++运算符重载

    一、前言 重载运算符的目的是为了让c++代码变的更直观、易读,主要在类中定义,让我们的类对象有着和普通变量一样的操作,例如:“<<”输出运算符,我们也希望类对象可以使用它,

    相关 c++】运算符重载

    您可以重定义或重载大部分 C++ 内置的运算符。这样,您就能使用自定义类型的运算符。 重载的运算符是带有特殊名称的函数,函数名是由关键字 operator 和其后要重载的运

    相关 c++运算符重载

    什么是运算符重载? 运算符重载是通过创建运算符函数实现的,运算符函数定义了重载的运算符将要进行的操作。运算符函数的定义与其他函数的定义类似,惟一的区别是运算符函数的

    相关 C++】 运算符重载

    1、一元运算符 运算符重载是`C++`的一大特色,以函数重载的形式出现,函数名为关键字operator后跟着一个运算符,这些函数可以作为类的成员函数实现,也可以作为类的友