文章目录
说在前面:C++将C语言中的左移运算符(<<)进行了运算符重载,变成了与流对象cout配合使用的流插入运算符;将右移运算符(>>)进行了运算符重载,变成了与流对象cin配合使用的流提取运算符,这就是利用了运算符重载。
运算符重载格式:
函数类型 operator 运算符名称(形参表)
{ 对运算符重载处理 }
例如:
A operator + (A &);
重载了类A的“+”运算符
“operator +“重载了运算符”+”
1.双目运算符重载
1.1 operator +
功能:用"+"实现两个复数对象的相加
1.重载为类的成员函数
#include <iostream>
using namespace std;
class Complex
{
private:
double real; //定义实部
double imag; //定义虚部
public:
//构造函数
Complex(){
real = 0.0;
imag = 0.0;
}
Complex(double r, double i){
real = r;
imag = i;
}
//输出实部虚部
void display(){
cout << "(" << real << ", " << imag << "i)" << endl;
}
//重载运算符 +
Complex operator +(Complex &c2){ //加号实现了两个对象的以下功能
Complex c;
c.real = this->real + c2.real;
c.imag = this->imag + c2.imag;
return c;
}
};
int main(){
Complex c1(3, 4), c2(4, 5), c3;
//定义3个复数对象,c3用于存放c1对象与c2对象的和
c3 = c1 + c2; //利用重载的+进行对象运算
cout << "c1 = ";
c1.display();
cout << "c2 = ";
c2.display();
cout << "c1 + c2 = ";
c3.display();
system("pause");
return 0;
}
2.重载为类的友元函数
#include <iostream>
using namespace std;
class Complex
{
private:
double real; //定义实部
double imag; //定义虚部
public:
//构造函数
Complex(){
real = 0.0;
imag = 0.0;
}
Complex(double r, double i){
real = r;
imag = i;
}
//输出实部虚部
void display(){
cout << "(" << real << ", " << imag << "i)" << endl;
}
//重载运算符 +
friend Complex operator+(Complex &c1 ,Complex &c2);
};
Complex operator +(Complex &c1, Complex &c2)
{
Complex c;
c.real=c1.real+c2.real;
c.imag=c1.imag+c2.imag;
return c;
}
int main(){
Complex c1(3, 4), c2(4, 5), c3;
//定义3个复数对象,c3用于存放c1对象与c2对象的和
c3 = c1 + c2; //利用重载的+进行对象运算
cout << "c1 = ";
c1.display();
cout << "c2 = ";
c2.display();
cout << "c1 + c2 = ";
c3.display();
system("pause");
return 0;
}
- 重载为友元函数与成员函数的主要区别在于其参数个数不同。
- 成员函数通过this指针传递给运算符左边的操作数,而友元函数则没有this指针,必须显式传递所有参数。
- 对+进行运算符重载之后,可以实现两个对象内部相应数据的运算,扩大了+号可运算数据的集合,同时也方便了很多
警告:上述代码不能实现c3 = 3 + c2,原因是与形参类型不匹配,重载之后的+号只能实现对象之间的相加
1.2 operator >
功能:比较两个字符串的大小
#include <iostream>
using namespace std;
class String
{
private:
char *p;
public:
//构造函数
String(){
p = NULL;
}
String(char *str){
p = str;
}
//输出字符串
void display(){
cout << p;
}
//重载 > 运算符为友元函数
friend bool operator>(String &string1, String &string2);
};
bool operator>(String &string1, String &string2)
{
if (strcmp(string1.p, string2.p)>0)
return true;
else
return false;
}
int main()
{
String string1("Hello"), string2("Book");
cout << (string1>string2) << endl;
system("pause");
return 0;
}
2.单目运算符重载
2.1 operator ++(前置)
- 格式:函数类型 operator ++( );
有一个Time类,包含数据成员minute和sec,模拟秒表,每次走一秒,满60秒进一分钟,此时秒又从0开始算。要求输出分和秒的值。
#include <iostream>
using namespace std;
class Time
{
private:
int minute;
int sec;
public:
//构造函数
Time() { minute = 0; sec = 0; }
Time(int m, int s):minute(m), sec(s) {}
//输出时间
void display() { cout << minute << ":" << sec << endl; }
//重载前置++运算符
Time operator++();
};
Time Time::operator++(){
sec++;
if (sec >= 60)
{
sec -= 60;
++minute;
}
return *this;
}
int main(){
Time time1(34, 0);
for (int i = 0; i<61; i++) //模拟时间过去了61秒
{
++time1;
time1.display();
}
system("pause");
return 0;
}
2.2 operator ++(后置)
- 格式:函数类型 operator ++(int);
#include <iostream>
using namespace std;
class Time
{
private:
int minute;
int sec;
public:
//构造函数
Time() { minute = 0; sec = 0; }
Time(int m, int s):minute(m), sec(s) {}
//输出时间
void display() { cout << minute << ":" << sec << endl; }
//重载前置++运算符
Time operator++();
//重载后置++运算符
Time operator++(int);
};
Time Time::operator++(){
sec++;
if (sec >= 60)
{
sec -= 60;
++minute;
}
return *this;
}
Time Time::operator++(int)
{
Time temp(*this);
sec++;
if (sec >= 60)
{
sec -= 60;
++minute;
}
return temp;
}
int main(){
Time time1(34, 59), time2;
cout << " time1 : ";
time1.display();
++time1;
cout << "++time1: ";
time1.display();
time2 = time1++; //time2为自增前的值
cout << "\ntime2 = time1++;\ntime1 : ";
time1.display();
cout << "time2 : ";
time2.display();
system("pause");
return 0;
}
3.重载流插入运算符和流提取运算符
Q:为什么流插入运算符和流提取运算符只能使用友元函数,却不可以使用成员函数呢?
A:因为调用该重载运算符的对象分别是istream类和ostream类对象,并不是用户自定义的类对象,所以无法把<<和>>重载为用户自定义类的成员函数。
3.1 operator <<
功能:利用<<输出对象信息
#include <iostream>
using namespace std;
class Complex
{
private:
double real;
double imag;
public:
//构造函数
Complex(){
real = 0;
imag = 0;
}
Complex(double r, double i){
real = r;
imag = i;
}
//对+运算符重载
Complex operator + (Complex &c2);
//对<<运算符重载
friend ostream& operator <<(ostream&, Complex&);
};
Complex Complex::operator + (Complex &c2)
{
return Complex(real + c2.real, imag + c2.imag);
}
ostream& operator << (ostream& output, Complex& c)
{
output << "(" << c.real << "+" << c.imag << "i)" << endl;
return output;
}
int main()
{
Complex c1(2, 4), c2(6, 10), c3;
c3 = c1 + c2; //用重载的+进行对象运算
cout << c3 << c1; //用重载的cout进行对象输出
system("pause");
return 0;
}
Q:为什么ostream& operator << (ostream& output, Complex& c)的返回值是ostream对象的引用?
A:因为cout << c3 << c1是一个对象一个对象输出的,先输出c3对象,然后返回一个cout,再进行cout<<c1;
3.2 operator >>
功能:利用>>输入对象信息
#include <iostream>
using namespace std;
class Complex
{
private:
double real;
double imag;
public:
//重载<<运算符用来输出对象信息
friend ostream& operator << (ostream&, Complex&);
//重载>>运算符用来读取对象信息
friend istream& operator >> (istream&, Complex&);
};
ostream& operator << (ostream& output, Complex& c)
{
output << "(" << c.real << "+" << c.imag << "i)";
return output;
}
istream& operator >> (istream& input, Complex& c)
{
cout << "input real part and imaginary part of complex number:";
input >> c.real >> c.imag;
return input;
}
int main()
{
Complex c1, c2;
cin >> c1 >> c2;
cout << "c1=" << c1 << endl;
cout << "c2=" << c2 << endl;
return 0;
}
4.重载运算符总结
- 1.不允许用户自定义新的运算符,只能对已有的C++运算符进行重载
- 2.C++中不允许重载的运算符有5个:成员访问运算符( . )、成员指针访问运算符( * )、域运算符( :: )、长度运算符( sizeof )、条件运算符( ?: )
- 3.C++中允许重载的运算符有(见图)
- 4.重载运算符不可以改变运算对象的个数
- 5.重载运算符不能改变运算符的优先级别
- 6.重载运算符不能改变运算符的结合性
- 7.重载运算符的函数不能有默认参数(会与4相矛盾)
- 8.重载运算符的操作对象中必须有一个是用户自定义的类对象
- 9.理论上可以将运算符重载为执行任意操作的符号,但是由于可读性较差,不容易理解,所以应当使运算符重载之后的功能还之前的功能类似
- 10.运算符重载扩展了原运算符可计算的数据类型的边界
5.不同类型数据间的转换
5.1 普通数据类型之间的转换
隐式类型转换
int i = 10;
i = 3.14 + i;
- 在进行i = 3.14 + i;时,编译系统会把3.14看成double型数据处理,然后将+号右侧的 i 转换成double型,再与3.14相加,得到和13.14,再向整形变量i赋值,将13.5舍去小数位变成13,然后赋值给i。
- 这一转换过程由编译器自动完成,用户不需干预,这种转换称为隐式转换
显式类型转换
int i = 10;
double d = (double) i;
- 将整型 i 强制转换成double型的10.0再赋值给double型的d
- 强制转换可能会导致数据的精度缺失
5.2 转换构造函数
- 转换构造函数只有一个形式参数,这个参数可以是基本数据类型,也可以是一个某一个类的引用对象
1.参数为基本数据类型
Complex(double r){
real = r;
imag = 0.0;
}
- 将一个基本数据类型转化为某类一个对象
2.参数为某类对象的引用
Teacher(Student &s){
this->num = s.num;
this->sex = s.sex;
strcpy(this->name,s.name);
}
- 将一个A类对象转化为另一个B类对象
5.3 类型转换函数
- 类型转换函数就是在类中定义一个成员函数,其作用是将某类对象转换为某种基本数据类型。
- 函数格式:类名 :: operator 基本数据类型名(){ 具体转换语句 }
- 例如:A :: operator float ( ){ return x+y; }
功能:将Complex对象转化为其实部double型数据返回
#include <iostream>
using namespace std;
class Complex
{
private:
double real;
double imag;
public:
//构造函数
Complex(){
real = 0;
imag = 0;
}
Complex(double r, double i){
real = r; imag = i;
}
//类型转换函数;将Complex对象转化为double型数据,
//输出的是该对象的实部数据
operator double()
{
return real;
}
};
int main()
{
Complex c1(3, 4), c2(5, -10), c3;
double d;
d = 2.5 + c1;
cout << d << endl;
return 0;
}
5.4 类型转换总结
点击该链接,查看我的其他关于数据存储的博客:数据如何存储