()的 重载[]的 重载->的 重载在编程中,多态的体现就是一个操作接口具有表现多种不同形态的能力,对不同的输入有不同的处理方式。例如, + 运算符,既可以适用于整数的相加,也可以适用于浮点数的相加,这就是多态性的体现。
C++中的多态是是通过绑定 来实现的,其中绑定指将一个标识符名称与一段函数代码结合起来。依据绑定实现的时期,可以分为 编译时的绑定 和 运行时的绑定 。
编译时的绑定 ,故名思意,在编译器对代码进行编译的时候就已经完成了绑定。而 运行时的绑定 需要等到程序运行的时候才将标识符和相应的行数代码结合起来。
在C++中 函数的重载 是一种静态多态性,是通过 编译时绑定 来完成的。
在C++中 运算符的重载 是一种动态多态性,是通过 运行时绑定 来完成的。
运算符重载让我们能够使用系统里面预先定义好的运算符进行相应运算。例如 定义一个 复数类,这是C++原生类型中不包含的类型。那么我们若想要通过C++中的运算符来完成复数的运算,则需要重载相应的运算符来实现。
C++ 几乎可以重载全部C++中已经有的运算符,但不能重载以下运算符:
| 运算符 | 描述 |
|---|---|
“.” | 成员访问运算符; |
“.*”、->* | 成员指针访问运算符; |
“::” | 域运算符; |
“sizeof” | 长度运算符; |
“?:” | 条件运算符。 |
重载运算符是通过定义类的成员函数来实现的,重载函数名是由关键字 operator 和其后要重载的运算符符号构成的。其格式示意如下:
函数类型 operator 运算符(形参列表){
// 函数体
}
例如,定义一个复数类:
class Complex {
private:
double r; // 实部
double i; // 虚部
public:
// 构造一个复数对象:指定实部和虚部的值作为该复数对象的实部和虚部
Complex(double r = 0.0, double i = 0.0) : r(r), i(i) { }
Complex operator+(const Complex& c2) const {
// 将一个临时无名复数对象用作返回值
return Complex(r + c2.r, i + c2.i);
}
Complex operator-(const Complex& c2) const {
// 同理
return Complex(r - c2.r, i - c2.i);
}
void print() const {
cout << r << " + " << i << "j" << endl;
}
};
与其他函数一样,重载运算符有一个返回类型和一个参数列表。除后置++、–外,其中形参的个数为该运算符的操作数的个数减1。
单目运算符是只对一个操作数进行操作的运算符。如位运算符、自增/自减运算符
如果要重载 U 为类 成员函数,使之能够实现表达式 U oprd,其中 oprd 为A类对象,则 U 应被重载为 A 类的成员函数,无形参。
经重载后,表达式 U oprd 相当于 oprd.operator U()
例如:
++和-- 的重载如果要重载 ++或–为类成员函数,使之能够实现表达式 oprd++ 或 oprd-- ,其中 oprd 为A类对象,则 ++或-- 应被重载为 A 类的成员函数,且具有一个 int 类型形参。
经重载后,表达式 oprd++ 相当于 oprd.operator ++(0)
例如:
关系运算符包括 < 、 > 、 <= 、 >= 、 ==。现在我们通过重载关系运算符来实现两个复数类实例的关系比较。在此我们定义:
实现和调用测试如下:
#include <iostream>
#include <cmath>
using namespace std;
class Complex {
private:
double r; // 实部
double i; // 虚部
public:
Complex(double r = 0.0, double i = 0.0) : r(r), i(i) { }
Complex operator+(const Complex& c2) const {
return Complex(r + c2.r, i + c2.i);
}
Complex operator-(const Complex& c2) const {
return Complex(r - c2.r, i - c2.i);
}
// 计算复数的模长
double length()
{
return pow((pow(r, 2)+pow(i,2)),0.5);
}
// 重载关系运算符 " == "
bool operator == (const Complex cplx)
{
if(r == cplx.r && i == cplx.i)
{
return true;
}else{
return false;
}
}
// 重载关系运算符 " > "
bool operator > (Complex cplx){
if(length() > cplx.length()){
return true;
}
return false;
}
// 重载关系运算符 " < "
bool operator < (Complex cplx){
if (length() < cplx.length()) {
return true;
}
return false;
}
// 重载关系运算符 " >= "
bool operator >= (Complex cplx) {
double length = cplx.length();
if (this->length() > length || this->length() == length) {
return true;
}
return false;
}
// 重载关系运算符 " >= "
bool operator <= (Complex cplx) {
double length = cplx.length();
if (this->length() < length || this->length() == length) {
return true;
}
return false;
}
void print() const {
cout << r << " + " << i << "j" << endl;
}
};
int main(){
Complex c1(3, 4), c2(5, 3), c3(4, 3);
cout << "c1.length() = " << c1.length() << "\n";
cout << "c2.length() = " << c2.length() << "\n";
cout << "c3.length() = " << c3.length() << "\n";
if (c1 > c2) { cout << "c1 > c2\n"; }
else if(c1 < c2){ cout << "c1 < c2\n"; }
else if (c1 == c2) { cout << "c1 == c2\n"; }
if(c1 >= c2){ cout << "c1 >= c2\n"; }
else if (c1 <= c2) { cout << "c1 <= c2\n"; }
// 是否相等(虚部实部同时相等)
if(c1 == c3){
cout << "c1 == c3\n";
}else{
cout << "c1 != c3\n";
}
}
Out[]:
c1.length() = 5
c2.length() = 5.83095
c3.length() = 5
c1 < c2
c1 <= c2
c1 != c3
C++中我们使用 流提取运算符 >> 和 流插入运算符 << 来 输入和 输出 内置的数据类型。
我们可以通过重载 流这两个运算符 ,以实现将他们用于自定义类型,表示提取和插入操作。
为了不需要创建对象,而直接调用函数,我们可以把运算符重载函数声明为类的友元函数。
例如,为了方便直接在控制台输入输出复数,我们为复数类重载输入输出运算符:
#include <iostream>
#include <cmath>
using namespace std;
class Complex {
private:
double r; // 实部
double i; // 虚部
public:
Complex(double r = 0.0, double i = 0.0) : r(r), i(i) { }
Complex operator+(const Complex& c2) const {
return Complex(r + c2.r, i + c2.i);
}
Complex operator-(const Complex& c2) const {
return Complex(r - c2.r, i - c2.i);
}
// 重载运算符 " << "
friend ostream& operator<<(ostream& output, const Complex& c){
output << c.r << " + " << c.i << "i";
return output;
}
// 重载运算符 " >> "
friend istream& operator>>(istream& input, Complex& D)
{
input >> D.r >> D.i;
return input;
}
};
int main(){
Complex c1(3, 4), c2;
cout << "c1 = " << c1 << endl;
cout << "Please enter the value of c2(real and image) : " << endl;
cin >> c2;
cout << "c2 = " << c2;
}
Out[]:
c1 = 3 + 4i
Please enter the value of c2(real and image) :
输入:
6 7
Out[]:
c2 = 6 + 7i
如图所示:

()的 重载函数调用运算符 () 可以被重载用于类的对象,例如:
#include <iostream>
using namespace std;
class Point {
private:
int x;
int y;
public:
// 构造函数
Point(int x0, int y0) {
x = x0;
y = y0;
}
// 默认构造函数
Point(){
x = 0;
y = 0;
}
void print() {
cout << "x = " << x << "; y = " << y << endl;
}
// 重载运算符函数
Point operator()(int stepx1, int stepy1, int stepx2, int stepy2) {
Point M;
M.x = x + stepx1 - stepx2;
M.y = y + stepy1 - stepy2;
return M;
}
};
int main(){
Point p1(10, 10), p2;
cout << "Point 1: ";
p1.print();
p2 = p1(20,5,15,3);
cout << "Point 2: ";
p2.print();
return 0;
}
Out[]:
Point 1: x = 10; y = 10
Point 2: x = 15; y = 12
可见,通过重载(),我们可以创建一个能够传递任意数目参数的运算符函数,本例中相当于传入了两个点的坐标。
[]的 重载下标运算符 [] 通常用于访问数组元素。最典型的应用场景,当我们自定义一个数据容器类如自定义一个数组类、链表类等等,想通过 下标运算符 [] 访问其中的某个元素时,这时我们重载[] 来实现。
例如,我们实现一个动态数组:
#include <iostream>
typedef int Rank;
using namespace std;
#define INIT_CAPACITY 3
template <typename T> class Vector {
protected:
Rank _size;
int _capacity;
T* _elem;
// 扩容
void _expand() {
if (_size < _capacity)return;
if (_capacity < INIT_CAPACITY) {
_capacity = INIT_CAPACITY;
};
T* oldElem = _elem;
_elem = new T[_capacity <<= 1];
for (int i = 0; i < _size; i++) {
_elem[i] = oldElem[i];
}
delete[] oldElem;
}
// 缩容
void _shrink() {
if (_capacity < INIT_CAPACITY << 1)return;
if (_size << 2 * _capacity)return;
T* oldElem = _elem = new T[_capacity >>= 1];
for (int i = 0; i < _size; i++) {
_elem[i] = oldElem[i];
}
delete[] oldElem;
}
public:
// 构造
Vector(int c = INIT_CAPACITY, int s = 0, T v = 0) {
_elem = new T[_capacity = c];
for (_size = 0; _size < s; _elem[_size++] = v);
}
// 析构
~Vector() {
delete[] _elem;
}
// 重载 下标运算符 []
T& operator[] (Rank r)const {
return _elem[r];
}
// 插入元素
Rank insert(Rank r, T const& e){
_expand();// 扩容
// 移动元素
for (int i = _size; i > r; i--){
_elem[i] = _elem[i - 1];
}
_elem[r] = e; // 放入新元素
_size++; // 容量加1
return r;
}
// 尾插
Rank append(T const& e){
return insert(_size, e);
}
};
int main(){
Vector<int> a;
a.append(1);
a.append(3);
a.append(5);
a.append(7);
a.append(9);
cout << "a[0] = " << a[0] << endl;
cout << "a[3] = " << a[3] << endl;
cout << "a[4] = " << a[4] << endl;
}
Out[]:
a[0] = 1
a[3] = 7
a[4] = 9