第十一章 使用类
记录CCPlus十一章内容,包含许多c++特性
博文地址
知识整理
运算符重载
运算符重载允许赋予c++运算符多种含义,c++根据操作数的数目和类型来决定采用哪种操作。
要重载运算符, 需使用运算符函数的特殊函数形式
operator op(argument list);
在运算符表示法中,运算符左侧的对象是调用对象,运算符右侧的对象是作为参数被传递的对象
c++对运算符重载的限制
-
重载后的运算符必须至少有一个操作数是用户定义的类型
-
使用运算符时不能违反运算符原来的句法规则
-
不能修改运算符的优先级
-
不能创建新运算符
-
不能重载以下运算符
sizeof
,.
,::
,?:
,typeid
,const_cast
,dynamic_cast
,reinterpret_cast
,static_cast
友元
c++公有类方法可以访问类对象私有部分,但有些情况会有许多限制。
举书上的例子,*重载运算符函数使用如下
A = B * 2.75; // A,B都为类对象
A = B.operator+(2.75); //转换为成员函数调用
但乘法还可以A = 2.75 * B
,此时的重载成员函数就不能用于这种情况, 这时候就需要非成员函数,又非成员函数不能访问私有部分,于是友元函数就出来了。
通过让函数称为类的友元,可以赋予该函数与类的成员函数相同的访问权限。
要创建友元函数,先将函数原型放在类声明中,并在原型前加上关键字friend
friend ClassName operator*(double m, const ClassName & t) const;
虽然函数是在类声明中声明的,但其不是成员函数,所以函数定义时不要使用::
,也不要在定义中使用关键字friend
ClassName operator*(double m, const ClassName & t) {
}
有了上述友元函数后,就可以使用A = 2.75 * B;
语句了。
书上还有一个常用友元的例子,重载<<
运算符
假设trip是一个类对象,要实现cout << trip;
如果使用一个成员函数来重载<<,就像使用成员函数重载*运算符那样,就必须trip << cout;
才能有效,但这样显然是不好的,这时可以使用友元函数重载
void operator<<(ostream &os, const ClassName & t){
}
这样就可以使用cout << trip;
,但这样不能和其他混合打印,如cout << "Trip: "<<trip<<" \n";
这里需要注意,ostream
类将operator<<()
函数实现为返回一个指向ostream
对象的引用,所以可以连续使用。
可以对友元函数采用同样的方法
ostream & operator<<(ostream & os, const ClassName & t){
os<<....
return os;
}
因为返回类型是ostream&
,所以可以连续使用。
那么,重载运算符是作为成员函数还是非成员函数呢?
对于某些运算符来说,成员函数是唯一合法的选择,但一般情况下,使用友元函数比较好。
类的自动转换和强制类型转换
c++存在内置类型转换,将一个标准型变量的值赋给另一种标准类型的变量时,若这两种类型兼容,则c++自动将这个值转换为接收变量的类型。
c++也可以将类定义与基本类型或另一个类相关,使得从一种类型转换为另一个类型有意义,如书上的例子
ClassName(double lbs); // 构造函数
ClassName cn;
cn = 19.6; // 自动转换使用构造函数
只有接受一个参数的构造函数才能作为转换函数,有两个参数不能转换,除非第二个参数有默认值。
同时,为了防止意外的类型转换,c++新增了关键字explicit,用于关闭隐式转换,只能显式转换。
explicit ClassName(double lbs);
ClassName cn;
cn = 19.6; // 不允许隐式转换
cn = ClassName(19.6);
cn = (ClassName)19.6 // 允许显式转换
c++还可以将类对象转换为内置类型,但必须使用转换函数
ClassName cn(34.6);
double host = double (cn); //有转换函数成立
double thin = (double) cn; // 有转换函数成立
转换函数要怎么创建呢?
operator typename();
同时需要注意以下几点
- 转换函数必须是类方法
- 转换函数不能指定返回类型
- 转换函数不能有参数
operator double();
ClassName::operator double(){
return (double)..;
}
和转换构造函数一样,转换函数也会发生意想不到的转换,所以也可以使用关键字exlicit
关闭隐式转换。
转换最好使用显式转换。
复习题
-
友元函数与成员函数之间的区别是什么?
成员函数是类定义的一部分,通过特定的对象来调用。友元函数不是类的组成部分,可以直接调用。
-
非成员函数必须是友元函数才能访问类成员吗?
要访问私有成员,必须是友元函数
-
哪些运算符不能重载?
sizeof
,.
,.*
,::
,?:
-
在重载运算符
=
,()
,[]
和->
时,有什么限制?以上运算符必须使用成员函数定义,不能使用友元函数