C++:运算符重载

发布时间:2026/11/14 14:46:25
C++:运算符重载 引言本文围绕C类与对象板块中的运算符重载展开系统讲解其必要性、核心语法与常见注意事项。为什么要重载运算符假如你定义了一个类它表示“年/月/日”这样的日期class Date { public: Date(int year 1, int month 1, int day 1) { _year year; _month month; _day day; } void Print() { cout _year / _month / _day endl; } private: int _year; int _month; int _day; };如果你想在2026/8/31这个日期上加上60天或者想用两个日期相减以计算它们之间的间隔但原本的“”与“-”运算符并不对自定义类类型有效所以我们为了功能或工程需要必须给运算符赋予新的功能这就是运算符重载的必要性。运算符重载函数operatoroperator与普通运算符重载想要重载运算符需要运算符重载函数它由名字operator加上需要重载的运算符组成它的参数和需要重载的运算符的操作数一样多且参数的顺序和运算符的操作数的顺序一样。我们拿重载“日期类”的“-”为例。“-”是一个二元运算符我们想实现“日期” - “日期” 天数并且把这个重载作为类的成员函数那么需要在operator前加上“-”参数分别是“减数”“被减数”返回值就是int天数声明就是这样int operator-(const Date d);我们知道成员函数的第一个参数是隐藏的“ Date* const this”——“被减数”而第二个“减数”就是const Date d。需要注意的是1.重载的运算符的优先级和结合性与原先一致。2.operator无法通过链接语法中没有的操作符来创建新的操作符3.operator重载必须至少有一个类类型参数不能改变内置操作符原本的含义比如不能int operator(int x, int y))4.一个类需要重载那些操作符应视情况而定比如日期类重载减法以计算间隔没问题但是重载乘法是没有意义的。5.重载或者--时C通过规定operator是否有带有int参数来区分重载的是前缀还是后缀。带有int参数即为后缀没有就是前缀。Date operator();//重载前缀 Date operator(int);//重载后缀Date Date::operator() { *this 1; return *this; } Date Date::operator(int) { Date tmp *this; *this 1; return tmp; }虽然都是自增但后缀需要返回自增前的值所以我们只能先用临时的tmp记录旧值自增后返回故而返回类型为Date而不是Date6.有些运算符无法被重载像是sizeof .*成员指针解引用7.若要重载“和“建议重载为全局函数否则用起来很怪这点我们详细讲讲。如果我想实现“cout 日期类”直接打印出日期一开始可能会想到的是把它作为成员函数但问题在于成员函数的第一个参数永远是“ Date* const this那你只能ostream operator(ostream out) { return out d._year / d._month / d._day endl; }这样先不说那几个成员函数的访问问题用起来也很诡异因为你必须反过来int main(){ Date d1(2026,8,31); d1 cout; return 0 }这显然不是我们需要的。最好的方法是把它设为全局函数同时在类中进行“友元声明”友元声明可以运行函数访问private中的参数而全局函数就能改变日期类类型参数的位置。//Date.h class Date { //友元函数声明 friend istream operator(istream in, Date d);//输出重载 friend ostream operator(ostream out, const Date d);//输入重载 public: Date(int year 1, int month 1, int day 1) { _year year; _month month; _day day; } private: int _year; int _month; int _day; }; //全局函数 ostream operator(ostream out, const Date d); istream operator(istream in, Date d); //Date.cpp ostream operator(ostream out, const Date d) { return out d._year / d._month / d._day endl; } istream operator(istream in, Date d) { int year 0; int month 0; int day 0; cout 请输入日期:; in year month day; if (!isValidDate(year, month, day))//检查输入的日期是否合法 { cout 输入的日期无效 endl; return in; } d Date(year, month, day); return in; }赋值运算符重载赋值运算符重载是一个默认成员函数用于完成两个已存在的对象之间的赋值它和拷贝构造的区别在于后者是要给一个正在创建的对象赋值。默认成员函数在没有自己实现时编译器会自己创建一个对于内置类型成员进行浅拷贝而对于自定义类型则会调用它的赋值重载函数。这种函数自然和拷贝构造一样有个老生常谈的规矩对于像Date日期这样的类默认的赋值重载没什么问题但对于像Stack这样成员变量指向了空间那就要自己实现。通常而言如果一个类实现了析构并释放了资源那么赋值重载务必要自己实现。const成员函数被const修饰的成员函数长这样const放在参数列表的后面void Print() const { cout _year - _month - _day endl; }这里的const本质上是修饰隐含的this指针把 Date* const this 变成了 const Date* const this 。二者的含义分别是this的指向不可改变。this指向的东西不可改变取地址运算符重载对取地址的重载是一个非常非常大的雷点总结起来一句话若非极其特殊的场景否则千万不要对取地址运算符进行重载因为重载后可能无法返回对象的真实地址这非常反直觉如果一定要重载记得const和非const的版本都要实现。

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询