运算符重载
C++允许将运算符重载到用户定义的类型,例如,使用+将两个类对象相加。
重载运算符要使用运算符函数:
operatorop(argument-list);
使用方法:
operator+() //重载+运算符
这里给出一个简单的复数类,并重载了运算符,实现复数的加、减、乘运算
假设a=(A,Bi),c=(C,Di) 复数的运算法则:
- 加法:a+c = (A+C,(B+D)i)
- 减法:a-c = (A-C,(B-D)i)
- 乘法:a * c = (A * C-B * D,(A * D + B * C)i)
- 乘法:a * x = ( A * x,Bi * x) x为实数
class Complex
{
private:
double real;
double imag;
public:
Complex();
Complex(double r, double i);
Complex operator+(const Complex &a) const;
Complex operator-(const Complex &a) const;
Complex operator*(const Complex &a) const;
Complex operator*(double x) const;
};
Complex Complex::operator+(const Complex &a) const{ //第二个const是为了确保this所指对象不被修改
Complex temp;
temp.real = this->real + a.real;
temp.imag = this->imag + a.imag;
return temp;
}
Complex Complex::operator-(const Complex &a) const{
Complex temp;
temp.real = this->real - a.real;
temp.imag = this->imag - a.imag;
return temp;
}
Complex Complex::operator*(const Complex &a) const{
Complex temp;
temp.real = this->real * a.real - this->imag * a.imag;
temp.imag = this->real * a.imag + this->imag * a.real;
return temp;
}
Complex Complex::operator*(double x) const {
Complex temp;
temp.real = this->real * x;
temp.imag = this->imag * x;
return temp;
}
如果result,a,c是Complex类的三个对象,则计算复数a和c的和,可以编写等式:result = a + c
编译器将上述语句转化为result = a.operator+(c)
,因此如果还有一个d对象,result = a + c + d
也是成立的,此语句将被编译器转化为result = a.operator+(c.operator+(d))
重载限制
- 重载后的运算符必须有一个操作数为用户定义的数据类型,这是为了防止用户为标准类型重载运算符,如将int类型相加的运算符+重载,将出现问题。
- 使用运算符时不能违反运算符原来的语法规则。例如,不能将求模运算符(%)重载成使用一个操作数
- 不能创建新的运算符
友元函数
C++严格控制类对象的私有数据访问,外部只能通过公有的类方法来访问私有数据。然而在特定情况下需要外部函数来访问类的私有数据,这种情况下,C++提供了另一种访问形式:友元。
通过让函数成为类的友元,可以使得该函数与类的成员方法有相同的权限。例如,Complex类提供了运算符 * 的重载,实现复数与实数相乘:Complex operator*(double x) const;
使用此重载,需要第一个操作数为类对象。
如语句:
result = a * 2
将被转化为下面的成员函数调用:
result = a.operator*(2)
但是当表达式写成result = 2 * a
时将出错,因为2
不是Complex类对象,没有operator*()方法。
为了解决此问题,应当编写一个原型如下的非成员函数来重载*:
Complex operator*(const double x, const Complex a);
但是非成员函数无法访问类的私有数据,所以需将此函数申明为Complex的友元函数,操作如下:
class Complex
{
private:
double real;
double imag;
public:
```
friend Complex operator*(const double x, const Complex a); //关键字friend表示类的友元函数
};
Complex operator*(const double x, const Complex a) { //函数定义时不需要friend关键字
Complex temp;
temp.real = a.real * x; //非友元函数无法访问a.real 与 a.imag
temp.imag = a.imag * x;
return temp;
}
有了上述声明和定义以后下面语句
result = 2 * a
将被转化为如下语句,从而调用定义的友元函数:
result = operator(2 , a)
常用友元:重载<<、>>运算符
为了输出类对象的内容,我们可以重载<<运算符:
class Complex
{
private:
double real;
double imag;
public:
```
void operator<<(std::ostream& os) const;
};
void Complex::operator<<(std::ostream& os) const {
os << "(" << real << "," << imag << "i)";
}
但是上述重载存在几个问题:
-
问题1: 该重载函数第一个参数为调用此方法的类对象,因此需要用以下语句来输出内的内容:
c << cout;
为解决此问题需要用到友元函数,调换参数顺序修改如下:
class Complex
{
private:
double real;
double imag;
public:
```
friend void operator<<(std::ostream& os, const Complex &a);
};
void operator<<(std::ostream& os, const Complex& a) {
os << "(" << a.real << "," << a.imag << "i)";
}
这样输出的表达式就变成cout << c
-
问题2:该重载函数无法做到
cout << c << a
连续输出因为上述表达式将转化为:
(operator<<(cout,c)) << a
(operator<<(cout,c))
无返回内容,输出c的内容后,表达式将变成<< a
,出现错误。所以对<<的重载函数需要返回第一个参数的引用,此时输出c内容后表达式将变为
cout << a
,再次输出a的内容。
正确重载<<的代码如下:
class Complex
{
private:
double real;
double imag;
public:
```
friend std::ostream& operator<<(std::ostream& os, const Complex &a);
};
std::ostream& operator<<(std::ostream& os, const Complex& a) {
os << "(" << a.real << "," << a.imag << "i)";
return os;
}
同理运算符>>的重载如下:
class Complex
{
private:
double real;
double imag;
public:
```
friend std::ostream& operator<<(std::ostream& os, const Complex &a);
friend std::istream& operator>>(std::istream& is, Complex &a);
};
std::ostream& operator<<(std::ostream& os, const Complex& a) {
os << "(" << a.real << "," << a.imag << "i)";
return os;
}
std::istream& operator>>(std::istream& is, Complex& a) {
std::cout << "Input real part of number :";
is >> a.real;
std::cout << "Input imaginary part of number :";
is >> a.imag;
return is;
}
完整代码与测试
complex0.h
#include <iostream>
class Complex
{
private:
double real;
double imag;
public:
Complex();
Complex(double r, double i);
Complex operator+(const Complex &a) const;
Complex operator-(const Complex &a) const;
Complex operator*(const Complex &a) const;
Complex operator*(double x) const;
Complex operator~() const;
friend Complex operator*(const double x, const Complex a);
friend std::ostream& operator<<(std::ostream& os, const Complex &a);
friend std::istream& operator>>(std::istream& is, Complex &a);
};
complex0.cpp
#include <iostream>
#include "complex0.h"
Complex::Complex() {
real = 0.0;
imag = 0.0;
}
Complex::Complex(double r, double i) {
real = r;
imag = i;
}
Complex Complex::operator+(const Complex &a) const{
Complex temp;
temp.real = this->real + a.real;
temp.imag = this->imag + a.imag;
return temp;
}
Complex Complex::operator-(const Complex &a) const{
Complex temp;
temp.real = this->real - a.real;
temp.imag = this->imag - a.imag;
return temp;
}
Complex Complex::operator*(const Complex &a) const{
Complex temp;
temp.real = this->real * a.real - this->imag * a.imag;
temp.imag = this->real * a.imag + this->imag * a.real;
return temp;
}
Complex Complex::operator*(double x) const {
Complex temp;
temp.real = this->real * x;
temp.imag = this->imag * x;
return temp;
}
Complex Complex::operator~() const{
Complex temp;
temp.real = this->real;
temp.imag = -this->imag;
return temp;
}
Complex operator*(const double x, const Complex a) {
Complex temp;
temp = a * x;
return temp;
}
std::ostream& operator<<(std::ostream& os, const Complex& a) {
os << "(" << a.real << "," << a.imag << "i)";
return os;
}
std::istream& operator>>(std::istream& is, Complex& a) {
std::cout << "Input real part of number :";
is >> a.real;
std::cout << "Input imaginary part of number :";
is >> a.imag;
return is;
}
main.cpp
#include <iostream>
#include "complex0.h"
using namespace std;
int main() {
Complex a(3.0, 4.0);
Complex c;
cout << "Enter a complex (q to quit):" << endl;
while (cin >> c) {
cout << "c is" << c << endl;
cout << "complex conjugate is " << ~c << endl;
cout << "a is " << a << endl;
cout << "a + c is " << a.operator+(c) << endl;
cout << "a - c is " << a - c << endl;
cout << "a * c is " << a * c << endl;
cout << "2 * a is " << 2 * a << endl;
cout << "a * 2 is " << a * 2 << endl;
cout << "Enter a complex (q to quit):" << endl;
}
}
result.png
网友评论