C++运算符重载(下)
C++运算符特殊重载
自增(++)、自减(–)的重载
关键在于前置和后置的区别
后置的 ‘++’ 或 ‘–’ 在写重载的时候需要一个无用的参数来标识
直接上代码吧
#include<iostream>
#include<string>
using namespace std;
class MM
{
public:
MM(string name,int faceScore):name(name),faceScore(faceScore){}
MM operator++(int);
MM operator++();
string& getName();
int& getFaceScore();
MM operator--(int);
MM operator--();
protected:
string name;
int faceScore;
};
int main()
{
MM mm1("Alice", 100);
MM mm2("Coco", 80);
MM temp("", 0);
temp = mm1++;
cout <<"temp:"<< temp.getName() << '\t' << temp.getFaceScore() << endl;
cout <<"mm1:"<< mm1.getName() << '\t' << mm1.getFaceScore() << endl;
cout << "---------------------------------" << endl;
temp = ++mm2;
cout << "temp:" << temp.getName() << '\t' << temp.getFaceScore() << endl;
cout << "mm2:" << mm2.getName() << '\t' << mm2.getFaceScore() << endl;
cout << "--------------------------------" << endl;
temp = mm2--;
cout << "temp:" << temp.getName() << '\t' << temp.getFaceScore() << endl;
cout << "mm2:" << mm2.getName() << '\t' << mm2.getFaceScore() << endl;
cout << "--------------------------------" << endl;
temp = --mm1;
cout << "temp:" << temp.getName() << '\t' << temp.getFaceScore() << endl;
cout << "mm1:" << mm1.getName() << '\t' << mm1.getFaceScore() << endl;
return 0;
}
MM MM::operator++(int)
{
return MM(this->name,this->faceScore++);
}
MM MM::operator++()
{
return MM(this->name,++this->faceScore);
}
string& MM::getName()
{
return this->name;
}
int& MM::getFaceScore()
{
return this->faceScore;
}
MM MM::operator--(int)
{
return MM(this->name,this->faceScore--);
}
MM MM::operator--()
{
return MM(this->name,--this->faceScore);
}
C++运算符流重载
输入流和输出流只能直接操作基本数据类型,但无法直接操作自定义类型(类或结构体),所以现在想直接使用输入流和输出流直接操作自定义类型的必须要对运算符进行重载。
声明:
- ostream和istream是类。
- 在重载函数传参的时候,如果想改变对象里面的数据就采用引用传参,如果不行改变对象里面的数据可以普通传参,也可以采用引用传参。
重载下面的运算符:
先采用类的成员函数重载方式重载
#include<iostream>
#include<string>
using namespace std;
class MM
{
public:
MM(string name="Alice",int faceScore=100):name(name),faceScore(faceScore){}
ostream& operator<<(ostream& out);
istream& operator>>(istream& in);
protected:
string name;
int faceScore;
};
int main()
{
MM mm;
mm.operator<<(cout);
cout << "请输入MM的姓名和颜值" << endl;
mm.operator>>(cin);
mm.operator<<(cout);
return 0;
}
ostream& MM::operator<<(ostream& out)
{
out << this->name << '\t' << this->faceScore << endl;
return out;
}
istream& MM::operator>>(istream& in)
{
in >> this->name >> this->faceScore;
return in;
}
上面的代码是可以实现的,也可以正常的输入和输出。但是
mm.operator<<(cout);
mm.operator>>(cin);
是显式调用,而且必须是显式调用才不会报错。那这样看来就比较不舒服了。用户希望的是下面的样子
cout<<mm;
cin>>mm;
而实现这样的效果,那么流运算符的重载就必须使用友元函数的方式进行重载
直接看代码
#include<iostream>
#include<string>
using namespace std;
class MM
{
public:
MM(string name="Alice",int faceScore=100):name(name),faceScore(faceScore){}
friend ostream& operator<<(ostream& out, MM& mm);
friend istream& operator>>(istream& in, MM& mm);
protected:
string name;
int faceScore;
};
int main()
{
MM mm;
cout << mm << endl;
cout << "请输入mm的信息:" << endl;
cin >> mm;
cout << mm << endl;
operator<<(cout, mm);
return 0;
}
ostream& operator<<(ostream& out, MM& mm)
{
out << mm.name << '\t' << mm.faceScore << endl;
return out;
}
istream& operator>>(istream& in, MM& mm)
{
in >> mm.name >> mm.faceScore;
return in;
}
对运算符流重载的小结:
- 可以使用类的成员函数重载
- 也可以使用友元函数重载
- 为了更简洁的隐式调用,亲近人的思维,一般使用友元函数重载
运算符重载之隐式转换
隐式转换在基本数据类型中是很常见的,就是使用不同的数据类型来相互赋值,然后还不报错。隐式转换就起到这样的作用。
在基本数据类型中,浮点型的变量赋值给整型变量,小数部分会被截断,只留下整数部分。
double dNum=3.1415926;
int iNum=dNum;
那么我们想使用自定义类型的对象赋值给基本数据类型的对象的时候,也想让它可以隐式转换的话就必须使用运算符重载。
基本语法:
operator 要转换的类型(){ return 对应的类型; }
operator前面不写返回值类型,后面的int是要转换的类型,()里面填参数,不能省略括号
直接看代码
#include<iostream>
using namespace std;
class MM
{
public:
MM(string name="Alice",int age=0):name(name),age(age){}
operator int()
{
return this->age;
}
protected:
string name;
int age;
};
int main()
{
MM mm("小可爱", 18);
int i = mm;
cout << i << endl;
return 0;
}
要重载其他类型的也可以,使用隐式转换的重载,并且要注明是哪个类型的就行,上面的代码是以重载int隐式转换的例子。
默认的 ‘=’ 重载运算符
在C++类中,如果没有写 ‘=’ 的运算符重载函数是会存在一个默认的重载函数,使得程序在执行类的对象赋值给类的对象语句的时候不会报错。
C++类中的默认存在的函数
- 默认的构造函数
- 默认的拷贝构造函数,浅拷贝
- 默认的 ‘=’ 重载函数
这些函数,如果自己没有写,是会在类中默认存在,如果写了,默认的就不存在了。
#include<iostream>
using namespace std;
class A
{
public:
A(int i,double d):i(i),d(d){}
A(A& obj):i(obj.i),d(obj.d)
{
cout<<"拷贝构造函数"<<endl;
}
protected:
int i;
double d;
};
int main()
{
A a(2,3.1);
A b(4,5.2);
a=b;
A c=a;
return 0;
}
把下面的代码下到上面的类的public中去
void operator=(A& obj)
{
i = obj.i;
d = obj.d;
cout << "赋值重载函数" << endl;
}
然后输出结果就是:
赋值重载函数 拷贝构造函数
如果赋值重载函数的参数传的不是引用类型,那在程序运行的时候还会调用一下拷贝构造函数,因为void operator=的参数列表中的A obj是进行下面操作
A obj=传进来的对象; 这个时候就是调用的拷贝构造
然后下面才开始执行operator=函数里面的内容
注意的细节就是:
A a;
A b=a;
A c;
c=a;
重载加常量
在之前的重载 '+'等运算符的时候,都是可以实现对象加一个常量的,但是它们并不存在交换律(也就是对象加常量可以,但是常量加对象就不行)。那怎么解决这个问题呢。就直接使用友元重载就可以了。
#include<iostream>
using namespace std;
class MM
{
public:
MM(string name="",int age=0):name(name),age(age){}
MM operator+(int num)
{
return MM(this->name,this->age + num);
}
void print()
{
cout << this->name << '\t' << this->age << endl;
}
friend MM operator+(int num,MM mm);
protected:
string name;
int age;
};
int main()
{
MM mm("Alice", 4);
MM mm2 = mm + 6;
mm2.print();
MM mm3 = 5 + mm2;
return 0;
}
MM operator+(int num, MM mm)
{
return MM(mm.name,mm.age+num);
}
- 重载加常量的内容还有一个不正常的写法,但是并没什么用,了解即可。直接看代码就知道了。
#include<iostream>
using namespace std;
class MM
{
public:
MM(int age = 3):age(age){}
friend MM operator+(MM mm1, MM mm2);
protected:
int age;
};
int main()
{
MM mm1(4);
MM mm2;
mm2 = 5 + mm1;
MM mm3 = mm2 + 9;
return 0;
}
MM operator+(MM mm1, MM mm2)
{
return MM(mm1.age+mm2.age);
}
看到上面的代码能这样搞是没问题的,但前提是这个类里面只有一个属性(而且是基本数据类型)这样才能够使用强转。然后就能使用对象加常量和常量加对象的操作了。
|