一、重载运算符
1、可重载的运算符列表:
| 序号 | 运算符名称 | 运算符书写符号 |
| 1 | 双目算术运算符 | + (加),-(减),*(乘),/(除),% (取模) |
| 2 | 关系运算符 | ==(等于),!= (不等于),< (小于),> (大于),<=(小于等于),>=(大于等于) |
| 3 | 逻辑运算符 | ||(逻辑或),&&(逻辑与),!(逻辑非) |
| 4 | 单目运算符 | + (正),-(负),*(指针),&(取地址) |
| 5 | 自增自减运算符 | ++(自增),--(自减) |
| 6 | 位运算符 | | (按位或),& (按位与),~(按位取反),^(按位异或),,<< (左移),>>(右移) |
| 7 | 赋值运算符 | =, +=, -=, *=, /= , % = , &=, |=, ^=, <<=, >>= |
| 8 | 空间申请与释放 | new, delete, new[ ] , delete[] |
| 9 | 其他运算符 | ()(函数调用),->(成员访问),,(逗号),[](下标) |
2、不可重载的运算符列表:
| 序号 | 运算符名称 | 运算符书写符号 |
| 1 | 成员访问运算符 | . |
| 2 | 成员指针访问运算符 | .*和->* |
| 3 | 域运算符 | :: |
| 4 | 长度运算符 | sizeof |
| 5 | 条件运算符 | ?: |
| 6 | 预处理符号 | # |
下面用重载运算符“+”来做例子。
在.h头文件如下声明:
#ifndef __MAIN_H__ #define __MAIN_H__ #include#include #include class Score { public: double math; void MathScore(const double); double operator+(const Score& sc); Score operator+(const int mathSc); }; double average(const double totalScore, const int num); #endif // !__MAIN_H__
在.cpp文件这样定义和调用:
#include"main.h"
using namespace std;
void Score::MathScore(const double mathScore)
{
math = mathScore;
}
double Score::operator+(const Score& sc)//重载+号 用于对象相加
{
return (this->math + sc.math);
}
Score Score::operator+(const int mathSc)//重载+号 用于对象和数值
{
this->math = this->math + mathSc;
return *this;
}
double average(const double totalScore, const int num)
{
return (totalScore / num);
}
int main()
{
double total;
double ave;
Score s1;
s1.MathScore(85);
s1 = s1 + 5;//少算了5分,把5分加进去。对象+数值,等价于total=s1.operator+(5);
cout << s1.math << endl;
Score s2;
s2.MathScore(100);
cout << s2.math << endl;
total = s1+s2;//对象+对象;这一句等价于:total=s1.operator+(s2);
cout << total << endl;
ave = average(total,2);//求两个人math课程的平均值
cout << ave << endl;
return 0;
}
运行结果如下:
二、赋值运算符“=”
对象赋值,系统会调用一个拷贝赋值运算符(简称赋值运算符),可以自己进行赋值运算符的重载,如果不自己重载这个运算符,编译器会用默认的对象赋值规则为对象赋值,甚至在必要的情况下帮助我们重载赋值运算符,当然,编译器重载赋值运算符功能上可能比较粗糙,只能完成一些简单的成员变量赋值以及调用类类型成员变量所对应类中提供的拷贝赋值运算符。
下面我们自己手动来实现一个赋值运算符的重载例子。
在.h头文件中这样声明:
#ifndef __MAIN_H__ #define __MAIN_H__ #include#include #include class Score { public: double math; double English; double Chinese; void MathScore(const double); void ChineseScore(const double chScore); void EnglishScore(const double enScore); Score operator=(const Score& sc); }; #endif // !__MAIN_H__
在.cpp文件中这样实现:
#include"main.h"
using namespace std;
void Score::MathScore(const double mathScore)
{
math = mathScore;
}
void Score::ChineseScore(const double chScore)
{
Chinese = chScore;
}
void Score::EnglishScore(const double enhScore)
{
English = enhScore;
}
Score Score::operator=(const Score& sc)
{
math = sc.math;
Chinese = sc.Chinese;
English = sc.English;
return *this;
}
int main()
{
Score s1;
s1.MathScore(100);
s1.ChineseScore(85);
s1.EnglishScore(86);
cout << s1.math << endl;
cout << s1.Chinese << endl;
cout << s1.English << endl;
cout << endl;
Score s2;
s2 = s1; //格式为:s2.operator(s1)
cout << s2.math << endl;
cout << s2.Chinese << endl;
cout << s2.English << endl;
return 0;
}
注意:s2=s1;用的“=”重载是我们自己手动写的,不是系统自己重载的。
针对s2=s1;和“Score operator=(const Score& sc);”这行代码,有几点要说明:
(1)左侧对象s2就是operator=运算符里的this对象。s1就是operator=里面的形参。
如下所示:
Score operator = (const Score& sc);
s2 = s1
在Score Score::operator=(const Score& sc){}函数中,this表示的就是s2这个类对象,sc就是s1这个对象。
(2)operator=运算符的返回值通常是一个指向其左侧运算符对象的引用,也就是s2的引用。
(3)如果想禁止Score类型对象之间的赋值,可以在.h头文件中声明赋值运算符重载时,用private来修饰,如下:
private:
Score operator=(const Score& sc);
三、析构函数(释放函数)
1、析构函数与构造函数正好是相对的,或者说是相反的,定义对象的时候,系统会调用构造函数,对象销毁的时候,系统会调用析构函数。
2、析构函数是没有参数且没有返回值的。析构函数不能被重载(重载:可以有多个同名称,带不同个数参数或不同数据类型的参数的普通函数或者构造函数),一个类中只能有唯一一个析构函数。当一个对象在离开其作用域被销毁的时候,那么该对象的析构函数就会被系统调用。
析构函数的格式:
~类名( ){......}
如果不写自己的构造函数,编译器可能会生成一个“默认析构函数”,也可能不会生成一个“默认析构函数”,是否生成取决于具体需要。
3、析构函数的成员销毁
(1)当释放一个对象的时候,首先执行改对象所属类的析构函数的函数体,执行完毕后,该对象就被销毁,此时对象中的各种成员变量也会被销毁。
(2)成员变量的初始化和销毁顺序问题。
成员变量初始化的时候是在类中先定义的成员变量先进行初始化,销毁的时候是先定义的成员变量后销毁。
(3)如果是用malloc/new等分配的内存,则一般都需要自己释放(通过在析构函数中使用free/delete来释放内存)。
2022.07.08结。



