//操作符重载
只能重载现有的操作符
操作符重载其实一种函数替换:如
district2 = sid + sara;
district2 = sid.operator()+(sara); //隐式转换
ex:
mytime.h
class Time
{
private:
...
public:
Time operator+(const Time &t) const;
Time operator-(const Time &t) const;
Time operator*(double n) const;
};
mytime.cpp
Time Time::operator+(const Time &t) const
{
...
return time; //直接return变量会在返回创建其拷贝,所以没有问题(但是应该注意浅拷贝问题),返回局部变量的引用或指针就会有问题
}
于是:
time t,t1,t2;
可以用下列方式调用
t = t1 + 2; <-----> t = t1.operator+(t2);
//重载限制
1 重载后的操作符必须至少有一个操作数是用户定义的类型,这将防止用户为标准类型重载操作符。(例如,不能将减法操作符重载为两个double值的和)
2 重载后的操作符不能违反操作符原来的句法规则,例如,不能将求模操作符% 重载成使用一个操作数(原来的求模操作符需要两个操作数)
3 重载后的操作符优先级不变
4 不能定义新的操作符
5 不能重载下面的操作符
sizeof()
.
.*
::
?:
typeid RTTI操作符
const_cast
dynamic_cast
reinterpert_cast
static_cast
6 操作符重载可以通过成员函数(类函数)或普通函数重载,但下面的操作符只能通过成员函数重载
= 赋值操作符
() 函数调用操作符
[] 下标操作符
-> 通过指针访问类成员的操作符
//友元
友元有三种:
1 友元函数
2 友元类
3 友元成员函数
通过让函数成为类的友元,可以赋予该函数与类成员函数相同的访问权限
友元的用处
Time A,B
A = B*2.5; //因为重载了 *所以,A=B*2.5 --> A.operator*(2.5)
A = 2.5*B; //编译器无法重载
但是,通过编写普通函数重载--> Time operator*(double m, const Time &t)
A = 2.5*B //A = 2.5*B --> operator*(2.5, B),但是,这样无法获取Time的私有成员(用友元解决)
加入友元函数
class Time
{
...
friend Time operator*(double m, const Time &t);
...
};
友元函数不是Time类的成员函数,所以不加 Time:: 域名限定符
Time operator*(double m, const Time &t)
{
....
}
常用的友元:重载<<操作符,注意返回ostream以便实现 os << A << B 的效果
ostream& operator<< (ostream &os, const Time &t)
{
...
return os;
}
NOTE:friend关键字在类成员函数的定义中使用
NOTE:如果你同时定义了相同调用格式的 类成员函数与非类成员函数,会导致编译错误
//类的自动转换盒强制转换
C++不自动转换不兼容类型
int *p = 10; //type clash wrong!
int *p = (int *) 10 //right
自动转换构造函数
Stonewt(double lbs);
Stonewt myCat;
myCate = 19.6; //将会自动调用Stonewt(double lbs)创建一个对象,并将其内容复制到myCat中
等价的
Stonewet myCat = 260; <---> Stonewet myCat(260); <---> Stonewet myCat = Stonewt(260);
explicit Stonewt(double lbs); //关闭这种自动特性的隐式转换,不过仍可使用显式转换,如下:
myCate = (Stonewt)19.6; //显式转换
隐式转换发生在如下场景:
1 将Stonewet初始化为double值时
2 将double值复制给Stonewet对象时
3 将double值传值给接受Stonewet参数的函数时
4 返回值声明为一个Stonewet的函数,返回一个都变了时
还可以进行如下转换:
Stonewet Jumbo;
JumBo = 7300; //将7300的int型转换为double型,注意如果还有构造函数Stonewet Jumbo(long) 则因为int既可以转换为long,也可转换为double,因此调用存在歧义,编译错
//转换函数
使用转换函数将类类型转换为元类型(int ,double...)
转换函数如下声明
operator typeName();
StoneWet
{
operator int(); // 替换为nt Stone_to_Int更安全;
}
StoneWet::operator int();
{
return int (pounds + 0.5);
}
要注意以下几点:
1 转换函数必须是类方法
2 转换函数不能指定转换类型 //即连void都没有,但是却可以返回参数
3 转换函数不能有参数
//转换函数的缺点!如:
int ar[20];
...
Stonewet temp(14,4);
...
int Temp = 1;
...
cout << ar[tmep] << endl; //这里的类类型temp将会转换为int值,编译器不会报错
转换总结:
1 只有一个参数的类构造函数会转换,可以用explicit防止隐式转换
2 operator int();可以将类类型转换为int型
两种转换函数可能会混乱!
total = stoenwet1 + stonewet2;
可能的转换
1. stoenwet1.operator+(stonewet2);
2. operator+(stoenwet1, stonewet2);
3. 转换成double加法 //因为Stonewet有double构造函数,且定义了operator double()
//1,2会编译错;1,3 2,3则会混乱 vs会选择1,2
只能重载现有的操作符
操作符重载其实一种函数替换:如
district2 = sid + sara;
district2 = sid.operator()+(sara); //隐式转换
ex:
mytime.h
class Time
{
private:
...
public:
Time operator+(const Time &t) const;
Time operator-(const Time &t) const;
Time operator*(double n) const;
};
mytime.cpp
Time Time::operator+(const Time &t) const
{
...
return time; //直接return变量会在返回创建其拷贝,所以没有问题(但是应该注意浅拷贝问题),返回局部变量的引用或指针就会有问题
}
于是:
time t,t1,t2;
可以用下列方式调用
t = t1 + 2; <-----> t = t1.operator+(t2);
//重载限制
1 重载后的操作符必须至少有一个操作数是用户定义的类型,这将防止用户为标准类型重载操作符。(例如,不能将减法操作符重载为两个double值的和)
2 重载后的操作符不能违反操作符原来的句法规则,例如,不能将求模操作符% 重载成使用一个操作数(原来的求模操作符需要两个操作数)
3 重载后的操作符优先级不变
4 不能定义新的操作符
5 不能重载下面的操作符
sizeof()
.
.*
::
?:
typeid RTTI操作符
const_cast
dynamic_cast
reinterpert_cast
static_cast
6 操作符重载可以通过成员函数(类函数)或普通函数重载,但下面的操作符只能通过成员函数重载
= 赋值操作符
() 函数调用操作符
[] 下标操作符
-> 通过指针访问类成员的操作符
//友元
友元有三种:
1 友元函数
2 友元类
3 友元成员函数
通过让函数成为类的友元,可以赋予该函数与类成员函数相同的访问权限
友元的用处
Time A,B
A = B*2.5; //因为重载了 *所以,A=B*2.5 --> A.operator*(2.5)
A = 2.5*B; //编译器无法重载
但是,通过编写普通函数重载--> Time operator*(double m, const Time &t)
A = 2.5*B //A = 2.5*B --> operator*(2.5, B),但是,这样无法获取Time的私有成员(用友元解决)
加入友元函数
class Time
{
...
friend Time operator*(double m, const Time &t);
...
};
友元函数不是Time类的成员函数,所以不加 Time:: 域名限定符
Time operator*(double m, const Time &t)
{
....
}
常用的友元:重载<<操作符,注意返回ostream以便实现 os << A << B 的效果
ostream& operator<< (ostream &os, const Time &t)
{
...
return os;
}
NOTE:friend关键字在类成员函数的定义中使用
NOTE:如果你同时定义了相同调用格式的 类成员函数与非类成员函数,会导致编译错误
//类的自动转换盒强制转换
C++不自动转换不兼容类型
int *p = 10; //type clash wrong!
int *p = (int *) 10 //right
自动转换构造函数
Stonewt(double lbs);
Stonewt myCat;
myCate = 19.6; //将会自动调用Stonewt(double lbs)创建一个对象,并将其内容复制到myCat中
等价的
Stonewet myCat = 260; <---> Stonewet myCat(260); <---> Stonewet myCat = Stonewt(260);
explicit Stonewt(double lbs); //关闭这种自动特性的隐式转换,不过仍可使用显式转换,如下:
myCate = (Stonewt)19.6; //显式转换
隐式转换发生在如下场景:
1 将Stonewet初始化为double值时
2 将double值复制给Stonewet对象时
3 将double值传值给接受Stonewet参数的函数时
4 返回值声明为一个Stonewet的函数,返回一个都变了时
还可以进行如下转换:
Stonewet Jumbo;
JumBo = 7300; //将7300的int型转换为double型,注意如果还有构造函数Stonewet Jumbo(long) 则因为int既可以转换为long,也可转换为double,因此调用存在歧义,编译错
//转换函数
使用转换函数将类类型转换为元类型(int ,double...)
转换函数如下声明
operator typeName();
StoneWet
{
operator int(); // 替换为nt Stone_to_Int更安全;
}
StoneWet::operator int();
{
return int (pounds + 0.5);
}
要注意以下几点:
1 转换函数必须是类方法
2 转换函数不能指定转换类型 //即连void都没有,但是却可以返回参数
3 转换函数不能有参数
//转换函数的缺点!如:
int ar[20];
...
Stonewet temp(14,4);
...
int Temp = 1;
...
cout << ar[tmep] << endl; //这里的类类型temp将会转换为int值,编译器不会报错
转换总结:
1 只有一个参数的类构造函数会转换,可以用explicit防止隐式转换
2 operator int();可以将类类型转换为int型
两种转换函数可能会混乱!
total = stoenwet1 + stonewet2;
可能的转换
1. stoenwet1.operator+(stonewet2);
2. operator+(stoenwet1, stonewet2);
3. 转换成double加法 //因为Stonewet有double构造函数,且定义了operator double()
//1,2会编译错;1,3 2,3则会混乱 vs会选择1,2