C++之运算符重载
C++预定义中的运算符的操作对象只限于基本的内置数据类型,但是对于我们自定义的类型(类)是没有办法操作的,但是大多时候我们需要对我们定义的类型进行类似的运算,这个时候就需要我们对运算符进行重新定义,赋予其新的功能,以满足自身的需求
运算符重载规则
(返回类型说明符) operator(运算符) (<参数表>)
(1)为了防止对标准类型进行运算符重载,C++规定重载后的运算符的操作对象必须至少有一个是用户定义的类型
(2)使用运算符不能违反运算符原来的句法规则
(3)不能修改运算符原来的优先级
(4)不能创建一个新的运算符
(5)不能进行重载的运算符:成员运算符,作用域运算符,条件运算符,sizeof运算符,const_cast、dynamic_cast、reinterpret_cast、static_cast强制类型转换运算符
(6)大多数运算符可以通过成员函数和非成员函数进行重载但是下面这四种运算符只能通过成员函数进行重载: =赋值运算符,()函数调用运算符,[ ]下标运算符,->通过指针访问类成员的运算符。
自动类型转换
在C和C++中,如果编译器看到一个表达式或函数使用了一个不合适的类型,它经常会执行自动类型转换。在C++中,可以通过定义自动类型转换函数来为用户定义类型达到相同效果。这些函数有两种类型,分别为特殊类型的构造函数和重载运算符。
构造类型转换
// 测试构造函数的自动类型转换 class one { public: one() {} }; class two { public: two(const one&){} }; void f(two){} void main() { one ONE; f(ONE); return; }
当编译器看到f()传入的是one对象时,编译器检查f()的声明并注意到它需要一个two的对象作为参数,然后编译器检查是否有从对象one到two的方法,它发现了构造函数two::two(const one&),该构造函数被悄悄的调用,结果对象two()被传给f()
若要阻止构造函数转换,可以通过explicit关键字来修改构造函数
// 测试构造函数的自动类型转换 class one { public: one() {} }; class two { public: explicit two(const one&){} }; void f(two){} void main() { one ONE; f(ONE); return; }
1>d:\cplusstu\offer\test.cpp(60) : error C2664: 'f' : cannot convert parameter 1 from 'one' to 'two'
1> No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called
运算符转换
通过关键字operator后跟随想要转换的类型的方式,将当前类型转换为希望的类型,这种形式的运算符重载是独特的,因为没有指定一个返回类型。
// 测试构造函数的自动类型转换 class two { public: two(){} //explicit two(const one&){} }; class one { public: one() {} operator two(){return two();} }; void f(two){} void main() { one ONE; f(ONE); return; }
class string就是很好的自动转换的例子。在使用自动类型转换的过程中特别需要注意隐藏的缺陷和问题。