本文参考自:
在C++中,我们可以为用户定义的类定义运算符。这意味着C++能够为运算符提供对自定义类的特殊意义,这种能力称为运算符重载。例如,我们可以在像String这样的类中重载运算符“+”,这样我们就可以通过使用 + 来连接两个字符串。复数、小数、大整数中算术运算符也可能被重载。
A simple and complete example
#include <iostream>
using namespace std;
class Complex
{
private:
int real, imag;
public:
Complex(int r = 0, int i = 0)
{
real = r;
imag = i;
}
// This is automatically called when '+' is used with
// between two Complex objects
Complex operator+(Complex const &obj)
{
Complex res;
res.real = real + obj.real;
res.imag = imag + obj.imag;
return res;
}
void print() { cout << real << " + i" << imag << '\n'; }
};
int main()
{
Complex c1(10, 5), c2(2, 4);
Complex c3 = c1 + c2;
c3.print();
}
Output:
12 + i9
What is the difference between operator functions and normal functions?
运算符函数和普通函数有什么区别?
呃。。。运算符函数和普通函数没什么区别。唯一的区别是运算符函数的名称始终是operator关键字后面跟运算符符号,并且通过运算符符号调用(调用时省略operator)。
下例为全局运算符函数:
#include <iostream>
using namespace std;
class Complex
{
private:
int real, imag;
public:
Complex(int r = 0, int i = 0)
{
real = r;
imag = i;
}
void print() { cout << real << " + i" << imag << '\n'; }
// The global operator function is made friend of this class so
// that it can access private members
friend Complex operator+(Complex const &, Complex const &);
};
Complex operator+(Complex const &c1, Complex const &c2)
{
return Complex(c1.real + c2.real, c1.imag + c2.imag);
}
int main()
{
Complex c1(10, 5), c2(2, 4);
Complex c3 = c1 + c2;
c3.print();
return 0;
}
Output:
12 + i9
Can we overload all operators?
所有运算符都可以重载吗?结论是No
通过以下几种类型的函数可以实现运算符重载:
- Member Function 成员函数
- Non-Member Function 非成员函数
- Friend Function 友元函数
下列运算符可以被重载:
+ – * ⁄ % ^ & | ~
! = < > += -= *= ⁄= %=
^= &= |= << >> <<= >>= == !=
<= >= && || ++ -- , ->* ->
() [] new delete new[] delete[]
Example 1: Overloading ++ Operator
// CPP program to illustrate
// operators that can be overloaded
#include <iostream>
using namespace std;
class overload
{
private:
int count;
public:
overload()
: count(4)
{
}
void operator++() { count = count + 1; }
void Display() { cout << "Count: " << count; }
};
int main()
{
overload i;
// this calls "function void operator ++()" function
++i;
i.Display();
return 0;
}
Output:
Count: 5
当++
运算符作用于overload
类的对象时(在本例中为对象i
),该函数被调用。在上述程序中,定义了void operator ++()
运算符函数(在overload class
内部)。此函数将i
对象的count
值加1。
Example 2: Overloading ++ operator i.e. pre and post increment operator
// CPP program to demonstrate the
// Difference between pre increment
// and post increment overload operator
#include <iostream>
using namespace std;
class overload
{
private:
int count;
public:
overload(int i)
: count(i)
{
}
overload operator++(int) { return (count++); }
overload operator++()
{
count = count + 1;
return count;
}
void Display() { cout << "Count: " << count << endl; }
};
// Driver code
int main()
{
overload i(5);
overload post(5);
overload pre(5);
// this calls "function overload operator ++()" function
pre = ++i;
cout << "results of I = ";
i.Display();
cout << "results of preincrement = ";
pre.Display();
// this call "function overload operator ++()"function
i++; // just to show diff
i++; // just to show diff
post = i++;
cout << "Results of post increment = ";
post.Display();
cout << "And results of i , here we see difference : "
" ";
i.Display();
return 0;
}
Output:
results of I = Count: 6
results of preincrement = Count: 6
Results of post increment = Count: 8
And results of i , here we see difference : Count: 9
Example 3: Overloading [ ] operator
// CPP program to illustrate overloading the
// [ ] operator
#include <iostream>
using namespace std;
class overload
{
int a[3];
public:
overload(int i, int j, int k)
{
a[0] = i;
a[1] = j;
a[2] = k;
}
int operator[](int i) { return a[i]; }
};
int main()
{
overload ob(1, 2, 3);
cout << ob[1]; // displays 2
return (0);
}
Output:
2
Example 4 : Overloading -> operator
// CPP program to illustrate
// operators that can be overloaded
#include <bits/stdc++.h>
using namespace std;
class GFG
{
public:
int num;
GFG(int j) { num = j; }
GFG *operator->(void) { return this; }
};
// Driver code
int main()
{
GFG T(5);
GFG *Ptr = &T;
// Accessing num normally
cout << "T.num = " << T.num << endl;
// Accessing num using normal object pointer
cout << "Ptr->num = " << Ptr->num << endl;
// Accessing num using -> operator
cout << "T->num = " << T->num << endl;
return 0;
}
Output:
T.num = 5
Ptr->num = 5
T->num = 5
以下运算符不可被重载:
- Scope Resolution Operator (::)
- Ternary or Conditional Operator (?:)
- Member Access or Dot operator (.)
- Pointer-to-member Operator (.*)
- Object size Operator (sizeof)
- Object type Operator(typeid)
Example 5: Overloading this .(dot) operator
.(点)运算符不能重载,如果重载会报错。
// C++ program to illustrate
// Overloading this .(dot) operator
#include <iostream>
using namespace std;
class cantover
{
public:
void fun();
};
class X
{
cantover *p;
cantover &operator.() { return *p; }
void fun();
};
void g(X &x)
{
x.fun(); // X::fun or cantover::fun or error?
}
Output: Error
prog.cpp:12:23: error: expected type-specifier before ‘.’ token
cantover& operator.() { return *p; }
上述程序报错,类似的,上述不能重载的运算符试图重载都会报错。
Important points about operator overloading 运算符重载的一些要点
-
要使运算符重载起作用,至少有一个操作数必须是用户定义的类对象。
-
赋值运算符(Assignment Operator):编译器自动为每个类创建一个默认赋值运算符。默认赋值运算符将右侧值赋值给左侧(在大多数情况下都可以(此行为与复制构造函数相同))。
-
转换运算符(Conversion Operator):我们还可以定义一种将一种类型转换为另一种类型的转换运算符。
#include <iostream> using namespace std; class Fraction { private: int num, den; public: Fraction(int n, int d) { num = n; den = d; } // Conversion operator: return float value of fraction operator float() const { return float(num) / float(den); } }; int main() { Fraction f(2, 5); float val = f; cout << val << '\n'; return 0; }
Output:
0.4
重载的转换运算符必须是成员方法。其他运算符既可以是成员方法也可以是全局方法。
-
任何可用单个参数调用的构造函数都可以用作转换构造函数,可以用于隐式转换到正在构造的类型。
#include <iostream> using namespace std; class Point { private: int x, y; public: Point(int i = 0, int j = 0) { x = i; y = j; } void print() { cout << "x = " << x << ", y = " << y << '\n'; } }; int main() { Point t(20, 20); t.print(); t = 30; // Member x of t becomes 30 t.print(); return 0; }
Output:
x = 20, y = 20 x = 30, y = 0
References:
http://en.wikipedia.org/wiki/Operator_overloading
「如果这篇文章对你有用,请随意打赏」
如果这篇文章对你有用,请随意打赏
使用微信扫描二维码完成支付

comments powered by Disqus