长沙建设教育网站,怎么让网站绑定域名访问,建设人力资源网官网,莆田seo目录
编辑 一、运算符重载
1.1 运算符重载概念
1.2 全局运算符重载
1.3 运算符重载为成员函数
二、赋值运算符重载的特性
2.1 赋值运算符重载需要注意的点
2.2 赋值运算符重载格式
2.2.1 传值返回
2.2.2 传引用返回
2.2.3 检查自己给自己赋值
三、赋值运算符重载的…
目录
编辑 一、运算符重载
1.1 运算符重载概念
1.2 全局运算符重载
1.3 运算符重载为成员函数
二、赋值运算符重载的特性
2.1 赋值运算符重载需要注意的点
2.2 赋值运算符重载格式
2.2.1 传值返回
2.2.2 传引用返回
2.2.3 检查自己给自己赋值
三、赋值运算符重载的应用
四、总结 一、运算符重载
1.1 运算符重载概念 C为了增强代码的可读性引入了运算符重载运算符重载是具有特殊函数名的函数。也具有其返回值类型函数名字以及参数列表其返回值类型与参数列表与普通的函数类似。 这里虽然用了重载但是运算符重载和函数重载不是一个东西 函数重载允许函数名相同参数不同的函数存在 运算符重载让自定义类型的对象可以用运算操作符必须是C\C语法存在的运算符。 函数名字为关键字operator后面接需要重载的运算符符号。
函数原型返回值类型 operator 操作符 (参数列表)
1.2 全局运算符重载
使用全局的operator程序如下
#includeiostream
using namespace std;class Date
{
public:Date(int year 1, int month 1, int day 1){_year year;_month month;_day day;}//private:int _year;int _month;int _day;
};bool operator(const Date d1, const Date d2)
{return d1._year d2._year d1._month d2._month d1._day d2._day;
}int main()
{Date d1(2025, 3, 8);Date d2(2025, 3, 7);cout (d1 d2) endl;//cout (operator(d1, d2)) endl;//两种写法是一样的return 0;
} 上述程序中全局的运算符重载的形式为bool operator(const Date d1, const Date d2)这就需要把Date类的成员变量改为私有即注释掉private。 注赋值运算符重载成全局函数注意重载成全局函数时没有this指针了需要给两个参数。 那么这样操作就破坏了Date类的封装性。封装性如何保证 使用友元函数重载为成员函数常用。 1.3 运算符重载为成员函数 将上述程序作进一步修改
#includeiostream
using namespace std;class Date
{
public:Date(int year 1, int month 1, int day 1){_year year;_month month;_day day;}bool operator(const Date d){return this-_year d._year this-_month d._month this-_day d._day;}private:int _year;int _month;int _day;
};int main()
{Date d1(2025, 3, 8);Date d2(2025, 3, 7);cout (d1 d2) endl;cout d1.operator(d2) endl;//两种写法是一样的return 0;
} 运算符重载为成员函数的形式为bool operator(const Date d)这里需要注意的是左操作数是this指向调用函数的对象。
1.4 运算符重载需要注意的点
运算符重载的使用需要注意一下5点 1. 不能通过连接其他符号来创建新的操作符比如operator 2. 重载操作符必须有一个类类型参数 3. 用于内置类型的运算符其含义不能改变例如内置的整型不 能改变其含义 4. 作为类成员函数重载时其形参看起来比操作数数目少1因为成员函数的第一个参数为隐 藏的this 5. .* : : sizeof ?: . 注意以上5个运算符不能重载。 针对5中的.*可以写如下程序
class ob
{
public:void func(){cout void func() endl;}
};typedef void(ob::*pobfunc)()int main()
{pobfunc p ob::func;//成员函数取地址要用操作符不然取不到//等同于void (ob:: *pi)() ob::func;ob tmp;(tmp.*p)();//通过对象去调用成员函数的指针成员函数指针要传this//*p();//普通的函数指针的调用return 0;
} 函数指针和数组指针都是特殊的指针普通变量的重命名为typedef 类型 重命名 上述程序中typedef void(ob::*pobfunc)()是成员函数指针类型的重定义。其中pobfunc是指向ob类中成员函数的函数指针类型。
1. void (ob*::)() 函数指针类型它指向一个返回值为void且没有参数的成员函数。ob*::表示函数指针指向ob类的成员函数。
2. typedef void(ob*::pobfunc)() 使用typedef关键字重定义一个指向ob类中的成员函数的函数指针类型pobfunc。
二、赋值运算符重载
2.1 赋值运算符重载格式 参数类型const Date传递引用可以提高传参效率返回值类型Date返回引用可以提高返回的效率有返回值目的是为了支持连续赋值检测是否自己给自己赋值返回*this 要复合连续赋值的含义。 相较于传值传参和传引用传参。
2.1.1 传值返回 将1.3的程序在Date类中进行补充补充的程序为
Date operator(const Date d2)
{this-_year d2._year;this-_month d2._month;this-_day d2._day;return *this;//*this就是d1相当于拿到左操作数
} 因为Date operator(const Date d)中的Date表明是传值返回意味着return *this;不会返回*this而是返回它的拷贝拷贝以后或存放在寄存器中。 所以同类型的传值拷贝又会调用一个拷贝构造。
2.1.2 传引用返回 将1.3的程序在Date类中进行补充补充的程序为
Date operator(const Date d2)
{this-_year d2._year;this-_month d2._month;this-_day d2._day;return *this;//*this就是d1相当于拿到左操作数
}
2.1.3 检查自己给自己赋值 这可能会造成性能的浪费成员变量可能依赖于其他成员变量的值如果这些成员变量的值被覆盖可能会引发错误。 基于2.2.2可通过判断地址来进一步改写
Date operator(const Date d2)
{if(this ! d2){this-_year d2._year;this-_month d2._month;this-_day d2._day;}return *this;
}
2.2 赋值运算符只能重载成类的成员函数 C规定其他运算符可以重载成全局的赋值重载不可以只能重载为成员函数。 对于默认成员函数如果不写编译器会生成一份。如果放在全局类中没有编译器会生成一份那调用的时候会产生冲突。
class Date
{
public:Date(int year 1900, int month 1, int day 1){_year year;_month month;_day day;}int _year;int _month;int _day;
};
// 赋值运算符重载成全局函数注意重载成全局函数时没有this指针了需要给两个参数Date operator(Date left, const Date right)
{if (left ! right){left._year right._year;left._month right._month;left._day right._day;}return left;
}// error C2801: “operator ”必须是非静态成员 2.3 没有显式编译器会生成一个默认赋值运算符重载 不写赋值运算符重载编译器会不会生成默认的呢 - 会因为是6个默认成员函数之一。 默认生成的对内置类型会完成值拷贝浅拷贝对自定义类型会去再调用它的赋值。 怎么知道赋值默认生成的赋值的行为是什么 - 同拷贝构造。 那是不是意味着自定义赋值操作符重载就可以不写了呢 - 不是。 注意如果类中未涉及到资源管理赋值运算符是否实现都可以一旦涉及到资源管理则必 须要实现。
三、赋值运算符重载的应用 如果是内置类型编译器是可以调用相关指令的如果是自定义类型编译器首先会去看有没有重载运算符如果没有就会报错。
#includeiostream
using namespace std;class Date
{
public:Date(int _year 1, int _month 1, int _day 1){_year year;_month month;_day day;}Date operator(const Date d){if(this ! d){this-_year d._year;this-_month d._month;this-_day d._day;}return *this;}Print(){cout _year - _month - _day endl;}private:int _year;int _month;int _day;
};int main()
{Date d1(2025, 3, 9);Date d2(2025, 3, 9);d1 d2;Date d3(d1);d1 d2 d3;//自定义类型连续赋值是要有返回值的d3.Print();int i, j 0;cout (i j 10) endl;return 0;
} 程序Date d3(d1);为拷贝构造还是一个构造。构造是指对象创建实例化的时候自动调用的初始化。其他的构造可能是用一些普通的参数进行初始化而拷贝构造是用同类型一个存在的对象进行初始化要创建的对象。 程序d1 d2;已经存在的两个对象一个拷贝赋值给另一个这里边用到了运算符所以就要重载这个运算符。 程序d1 d2 d3;为自定义类型连续赋值是要有返回值的。 程序i j 10;内置类型支持连续赋值。执行动作为10赋值给j作为一个表达式这个表达式有返回值返回值就是左操作数j。同理再向左返回值为左操作数i。
四、总结 默认生成的函数行为总结 构造和析构内置类型不处理自定义类型调用对应的构造和析构。拷贝构造和赋值运算符重载内置类型值拷贝自定义类型调用对应的拷贝构造和赋值重载。