运算符重载
运算符重载是针对新类型数据(如用户自定义类型)的实际需要,对原有运算符进行适当的改造
运算符重载的规则
- C++中已有的运算符除了少数几个之外,全部可以重载。不能重载的运算符有:成员运算符
.
,指针运算符.*
,作用域运算符::
,sizeof
,三目条件运算符?:
。 - 重载不改变运算符的 优先级 结合律 和 操作数个数
- 重载运算符不能有二义性
- 不能创造新的运算符,如其他语言中的求幂运算符
**
,我们可以通过重载^
运算符来实现 - 运算符只能显式重载,不存在隐式重载。如:重载赋值运算符和加法运算符后,
object2 = object2 + object1;
语句成立,但这并不意味着+=
运算符会自动重载,因此object2 += object1;
语句不成立。 - 一般来说,运算符重载形式有两种,重载为类的成员函数和重载为类的友元函数。
- 友元函数没有隐含的参数this指针,所需操作数必须在参数列表里显式声明,很容易实现隐式类型转换。这样,对双目运算符,友元函数有2个参数,对单目运算符,友元函数有一个参数。但有些运算符不能重载为友元函数,它们是:= , () , [] 和 ->。
- 一般说来,单目运算符最好被重载为成员;对双目运算符最好被重载为友元函数,双目运算符重载为友元函数比重载为成员函数更方便。在第一个参数需要隐式类型转换时,使用友元函数重载运算符较好。友元函数也常用于运算符左右操作数类型不同的情况。但是,有的双目运算符还是重载为成员函数为好,例如,赋值运算符。因为,它如果被重载为友元函数,将会出现与赋值语义不一致的地方。
运算符重载为类的成员函数的一般语法形式为:
返回值类型 operator运算符(形参表) //operator是定义运算符重载函数的关键字
{
函数体;
}
运算符重载为类的友元函数的一般语法形式为:
friend 返回值类型 operator运算符(形参表)
{
函数体;
}
= 运算符重载 实现字符串拷贝
class StringPlus{ char* p; };
StringPlus& StringPlus::operator=(const StringPlus& s) {
if (s.p != NULL) {
if (p != NULL) delete[]p;
p = new char[strlen(s.p) + 1];
strcpy_s(p, strlen(s.p) + 1, s.p);
}
else if (p != NULL) {
delete[]p;
p = NULL;
}
return *this; //重载'='时特有的语句
}
int main() { StringPlus s1(str1), s1 = s2; ... } //重载'='的使用
++ 运算符重载
"++"运算符重载
#include <iostream>
using namespace std;
class Increase {
public:
Increase() { value = 0; }
void display() const { cout << value << '\n'; };
friend Increase operator ++ (Increase&); // ++前置
friend Increase operator ++ (Increase&, int); // 后置++
private: unsigned value;
};
Increase operator ++ (Increase& a) { //++n
a.value++; return a;
}
Increase operator ++ (Increase& a, int) { //n++
Increase temp(a); a.value++; return temp; //n先参与其他运算或调用,再进行自增
}
int main()
{
Increase a, b, n;
for (int i = 0; i < 10; i++) a = n++;
cout << "n = "; n.display(); cout << "a = "; a.display();
for (int i = 0; i < 10; i++) b = ++n;
cout << "n = "; n.display(); cout << "b = "; b.display();
}
程序运行结果:
n = 10
a = 9
n = 20
b = 20
[ ] 运算符重载
#include <iostream>
using namespace std;
class vector {
public:
vector(int n) { v = new int[n]; size = n; }
~vector() { delete[] v; size = 0; }
int& operator [] (int i) { return v[i]; }
private:
int* v; int size;
};
int main() {
vector a(5);
a[2] = 12;
cout << a[2] << endl;
}
( ) 运算符重载 实现数学函数的抽象
#include <iostream>
using namespace std;
class F {
public:
double operator() (double x, double y);
};
double F::operator() (double x, double y)
{ return x * x + y * y; }
int main(){
F f;
cout << f(5.2, 2.5) << endl; //形似函数 z=f(x, y)
}
cpp 1 :复数(a+bi)运算
#include <iostream>
using namespace std;
class Complex
{
public:
Complex(double r = 0, double i = 0) { Real = r; Image = i; }
Complex(int a) { Real = a; Image = 0; }
void print() const;
friend Complex operator+ (const Complex& c1, const Complex& c2);
friend Complex operator- (const Complex& c1, const Complex& c2);
friend Complex operator- (const Complex& c);
private:
double Real, Image;
};
Complex operator + (const Complex& c1, const Complex& c2)
{
double r = c1.Real + c2.Real; double i = c1.Image + c2.Image;
return Complex(r, i);
}
Complex operator - (const Complex& c1, const Complex& c2)
{
double r = c1.Real - c2.Real; double i = c1.Image - c2.Image;
return Complex(r, i);
}
Complex operator- (const Complex& c)
{
return Complex(-c.Real, -c.Image);
}
void Complex::print() const
{
cout << '(' << Real << " , " << Image << ')' << endl;
}
void main()
{
Complex c1(2.5, 3.7), c2(4.2, 6.5);
Complex c;
c = c1 - c2; // operator-(c1, c2)
c.print();
c = 25 + c2; // operator+(25, c2)
c.print();
c = c2 + 25; // operator+(c2, 52)
c.print();
c = -c1; // operator-(c1)
c.print();
}
cpp 2 :矩阵类的运算符重载:
class Matrix{ //矩阵类
int row, col;
int** p;
...
};
//定义一个所有元素全为value的矩阵
Matrix::Matrix(int row, int col, int value)
{
p = new int*[row]; //分配row个指针
for (int i = 0; i < row; ++i)
p[i] = new int[col]; //为每一个指针p[i]分配动态内存,大小为col
//即分配一个 row * col大小的数组空间用于存放矩阵的元素
for (int i = 0; i < row; i++)
for (int j = 0; j < col; j++)
p[i][j] = value; //初始化数组所有元素为 value
}
"-"运算符重载实现矩阵减法
Matrix& Matrix::operator-(const Matrix& B)
{
for (int i = 0; i < row; i++)
for (int j = 0; j < col; j++)
p[i][j] -= B.p[i][j];
}
"*"运算符重载实现矩阵乘法
Matrix Matrix::operator*(const Matrix& B) const
{
Matrix C(row, B.col, 0); //定义一个所有元素全为 0的矩阵
//若C=AB,则矩阵C的行数等于矩阵A的行数,C的列数等于B的列数。
for(int i = 0; i < row; i++)
for(int j = 0; j < B.col; j++)
for(int k = 0; k < col; k++)
C.p[i][j] += (p[i][k] * B.p[k][j]);
return C;
}
"+="运算符重载实现矩阵加法
Matrix& Matrix::operator+=(const Matrix& B)
{
for (int i = 0; i < row; i++)
for (int j = 0; j < col; j++)
p[i][j] += B.p[i][j];
return *this;
}
"*="运算符重载实现矩阵乘法
Matrix& Matrix::operator*=(const Matrix& B)
{
Matrix C(row, B.col, 0);
for (int i = 0; i < row; i++)
for (int j = 0; j < B.col; j++)
for (int k = 0; k < col; k++)
C.p[i][j] += (p[i][k] * B.p[k][j]);
*this = C;
return *this;
}
">>"运算符重载实现矩阵输入
istream& operator>>(istream& is, Matrix& A)
{
for (int i = 0; i < A.row; i++)
for (int j = 0; j < A.col; j++)
is >> A.p[i][j];
return is;
}
"<<"运算符重载实现矩阵输出
ostream& operator<<(ostream& out, Matrix& A)
{
for (int i = 0; i < A.row; i++) {
for (int j = 0; j < A.col; j++) {
out << A.p[i][j] << " ";
} //用cout << A.p[i][j] << " ";也可,不过不是传统意义上的<<运算符了
out << endl;
}
out << endl;
return out;
}
int main()
{
int rowA, colA, rowB, colB;
cin >> rowA >> colA >> rowB >> colB;
Matrix A = Matrix(rowA, colA);
Matrix B(rowB, colB);
cin >> A >> B; //输入矩阵A、B的元素
Matrix C(rowA, colB); //生成 rowA*colB的矩阵是为了方便存储矩阵加法和乘法的结果
C = A - B; cout >> C;
C = A * B; cout >> C;
A += B; cout >> A;
B *= A; cout >> B;
}
//由此可见,运算符重载后,矩阵的运算表达式可以非常简洁、明练、易懂
cpp 3 :有理数计算(有缺陷版本)
#include <iostream>
using namespace std;
class Rational
{
public:
Rational(long n, long d = 1); // 构造函数,把长整型转换成Rational类型
friend Rational operator+ (const Rational&, const Rational&);
friend ostream& operator<< (ostream&, const Rational&);
operator double(); // 类型转换函数
private: long Numerator, Denominator;
};
// 把长整型转换成Rational类型
Rational::Rational(long n, long d) { Numerator = n; Denominator = d; }
// 把 Rational 类型转换成 double 类型
Rational :: operator double()
{
return double(Numerator) / double(Denominator);
}
Rational operator+ (const Rational& r1, const Rational& r2)
{
long n, d;
n = r1.Numerator * r2.Denominator + r1.Denominator * r2.Numerator;
d = r1.Denominator * r2.Denominator;
return Rational(n, d);
}
ostream& operator << (ostream& output, const Rational& x)
{
output << x.Numerator << "/" << x.Denominator; return output;
}
int main()
{
Rational a(2, 4), b = (1, 2), c(0);
c = a + b; // 使用友员重载 “+” 和 缺省重载 “=”
cout << a << " + " << b << " = " << c << endl; // 以分数形式显示
// 以实数形式显示,调用类型转换函数:
cout << double(a) << " + " << double(b) << " = " << double(c) << endl;
c = b + Rational(1); // 调用构造函数作类型转换
cout << b << " + " << 1 << " = " << c << endl;
cout << double(b) << " + " << 1 << " = " << double(c) << endl;
return 0;
}