程序设计与算法三~C++面向对象程序设计~北大郭炜MOOC学习笔记~第四章:运算符重载(新标准C++程序设计)

以下内容为笔者手打,望读者珍惜,如有转载还请注明。

$4.1 运算符重载的概念和原理
同一运算符可以作用于不同类型的数据产生不同的行为,使得可以用来操作对象.
实质:编写以运算符作为名称的函数
返回值类型 operator运算符(参数表){

}
包含被重载的运算符的表达式会被编译成对运算符函数的调用,运算符的操作数称为函数调用时的
实参.运算的结果是函数的返回值.
运算符被重载为全局函数时,参数的个数等于运算符的目数(即操作数的个数);
运算符重载为成员函数时,参数的个数等于运算符的目数-1
//单目运算符:++,--,~,*,&
//双目运算符:&(与),|(或),^(按位异或),<<(左移),>>(右移),+,-,*,/,%

在C++中,“类名(构造函数参数表)”的写法表示生成一个临时对象.

$4.2 重载赋值运算符“=”
赋值运算符 “=” 要求左右两个操作数的类型是匹配的,或至少是兼容的.有时希望 “=” 两边的
操作数的类型即使不兼容也能够成立,这就需要对 “=” 进行重载.C++规定,“=” 只能重载为
成员函数.

$find 函数(隶属于string类)
string str1, str2;
int i;
str1 = "qwertyuuoesdi";
str2 = "uu";
char c = 'q';
i = str1.find(str2);//从串str1中查找时str2,返回str2中首个字符在str1中的地址
printf("%d\n",i);// 6(第七位,下标是6) 
i = str1.find(str2,5);//从str1的第5个字符(从下标是5)开始查找str2
printf("%d\n",i);// 6,如果不存在输出-1
i = str1.find(c);//在str1中查找字符o并返回第一个查找到的地址
printf("%d\n",i);// 0
i = str1.find("esjdsjk",2 , 2);//从str1中的第二个字符开始查找"esjdsjk"的前两个字符
printf("%d\n",i);// 9

我们将字符串从下标n开始,长度为m的字符串称为子串(n,m)
$substr函数(string类):用来求string对象的子串(n,m)
调用时,如果省略了长度m或者最终超过了字符串的长度,则求出来的字串就是从下标n开始一直到
字符串结束的部分.
例:string s1 = "this is ok";
string s2 = s1.substr(2 ,4);//从下标2开始长度为4的子串
s2 = s1.substr(2);//无长度参数,从下标2到字符串结束

$4.2 $4.3浅拷贝与深拷贝综合程序见guowei:operator= overload.cpp
$4.4运算符重载为友元函数
    一般情况下,将运算符重载为类的成员函数是比较好的选择,但有时,重载为成员函数不能
满足使用需求(比如说运算符作用的并不是类的对象),重载为全局函数又不能访问类的私有成员,
因此需要将运算符重载为类的友元函数.例如对于复数类的Complex对象,希望“c+5”和"5+c"都能
实现.将“+”重载为Complex类的成员函数能够解释c+5.而“5+c”,需要将“+”再次重载为全局函数,
并且该全局函数为Complex类的友元.
举例:class Complex{
    private:
        double real,imag;
    public:
        Complex(double r,double i):real(r).imag(i){}
        friend Complex operator + (double r,const Complex & c);//友元声明
        Complex operator + (double r){//+重载
            return Complex(real + r, imag);
        }
        Complex operator + (const Complex & c){
            return Complex(real + c.real, imag + c.imag);
        }
}
Complex operator + (double r,const Complex & c){    //另一个+重载
    return Complex(c.real+r,c.imag);
}
详见guowei::Complex

$4.6重载流插入与流提取运算符
    在C++中,左移运算符“<<”可以和cout一起用于输出,因此也被称为“流插入运算符”.实际上,
"<<"本来没有这样的功能,他是被重载了.cout是ostream类的对象,cin是istream类的对象
ostream类和cout都是在头文件ioatream里面声明的.
    我们没有办法修改ostream类和istream类,因此只能将"<<"和">>"重载为全局函数.
由于这两个函数需要访问Complex类的私有成员,我们在Complex类中将他们声明为友元.

参见guowei:overload of cin cout operator.cpp

$4.7重载类型强制转化运算符
    在C++中,类型的名字(包括类的名字)本身也是一种运算符,即类型强制转化运算符.类型
强制转化运算符是单目运算符,也可以被重载,但只能被重载为成员函数,不能重载为全局函数.
    经过适当的重载后,“(类型名)对象”这个对对象进行强制类型转化的表达式就等价于
“对象.operator类型名()”,即变成对运算符函数的调用.
下面的程序对double类型强制转化运算符进行了重载.

class Complex{
    double real,imag;
    public:
        Complex(double r,double i):real(r),imag(i){}
        operator double (){return real;}//重载强制类型转化运算符double
};
int main()
{
    Complex c(1.2,3.4);
    cout<<(double)c<<endl;//输出1.2
    double n=2+c;//等价于double n = 2+ c.operator double(c)
    cout<<n;//输出3.2
}
$4.8 重载自增,自减运算符
    自增运算符"++",自减运算符"--"都可以被重载,但是它们有前置、后置之分.以“++”为例,
假设obj是一个CDemo类的对象,“++obj”和“obj++”本应该是不一样的,前者的返回值应该是obj
被修改后的值,而后者的返回值应该是obj被修改前的值.
    C++规定,在重载“++”或“--”时,允许下一个增加了无用int类型形参的版本,编译器处理
“++”“--”前置的表达式时,调用参数个数正常的重载函数;处理后置表达式时,调用多出来一个
参数的重载函数.

前置运算符作为一元运算符重载:&类型无int
重载为成员函数:
T & operator++();
T & operator--();
重载为全局函数:
T1 & operator++(T2);
T1 & operator—(T2);
前置运算符返回值类型为引用.作成员函数时不需要参数,作全局函数时参数类型也是引用.

后置运算符作为二元运算符重载,多int无&
重载为成员函数:
T operator++(int);
T operator--(int);
重载为全局函数:
T1 operator++(T2,int);
T1 operator--(T2,int);
但是在没有后置运算符重载而有前置重载的情况下,
在vs中,obj++ 也调用前置重载,而dev则令 obj ++ 编译出错
后置运算符返回值不是引用(不需要).作成员函数时写一个int,作全局函数的时候引用+int.
默写:
CDemo & operator++();前置++成员函数
CDemo & operator++(CDemo&);前置++全局函数
CDemo operator++(int);后置++成员函数
CDemo operator++(CDemo&,int);后置++全局函数

$4.9运算符重载的注意事项
“()”,"[]","->",赋值运算符"="都只能重载为成员函数,不能重载为全局函数.

以上内容为笔者手打,望读者珍惜,如有转载还请注明。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值