C++ Primer阅读心得(第十四章)
2008-04-09 01:15
281 查看
1.不能重载的操作符,包括:
: : (域操作符)
.* (指针成员操作符)(这货很少用到啊)
.(点操作符)
?: (问号表达式)
2.不建议重载的操作符,包括:
因为无法保证求值顺序,不应该重载:逻辑与&&、逻辑或||、逗号运算符,
重载operator&之后会造成很多问题(尤其是返回类型与默认返回类型不一致时),所以避免重载operator&。
3.操作符重载的基本规则:
函数名称为:operator加上操作符
有返回类型、函数体和参数列表
一元操作符一个参数,二元操作符两个参数
成为类成员的操作符重载第一个参数被默认为this,所以参数个数再减一
只有调用操作符()可以有参数默认值,其他都不可以
操作符重载函数或者是类成员,或者必须含有一个类类型的参数(所以你不能重载内置类型的操作符)
只能重载已经存在的操作符,不能创造新的操作符(废话)
重载操作符的优先级和结合律与默认的保持一致
是不是很啰嗦?在这里举个例子吧。
4.下面将各种操作符的重载列在如下表中:
5.lambda表达式与函数对象:定义了函数调用操作符(operator())的类型的对象被称为函数对象,它们可以被调用函数那样子调用。
6.function类型:在c++当中,以下四种类型的对象是可以被调用的。
函数
函数指针
lambda表达式
可调用对象
在混合使用它们的时候,相当的不方便,因为它们是四种不同类型的对象。为了解决这一问题,c++11中新增了function类型模板,以调用形式(“返回值-参数列表”)为Type,可以兼容以上全部类型,让它们像同一个类型的对象一样工作。
注意:不能将重载函数直接放入function中,需要用函数指针明确指明或者lambda临时包装一下(这方法太经典了)。
7.显式类型转换符explicit:在c++11中,新增了显式类型转换符,用来阻止编译器利用定义好的类型转换符来进行隐式类型转换。增加了explicit的类型转换符必须显式调用类型转换才可以(static_cast等)。
8.类型转换的best practice:除了定义显式bool类型转换符之外,不要定义其他的类型转换。
: : (域操作符)
.* (指针成员操作符)(这货很少用到啊)
.(点操作符)
?: (问号表达式)
2.不建议重载的操作符,包括:
因为无法保证求值顺序,不应该重载:逻辑与&&、逻辑或||、逗号运算符,
重载operator&之后会造成很多问题(尤其是返回类型与默认返回类型不一致时),所以避免重载operator&。
3.操作符重载的基本规则:
函数名称为:operator加上操作符
有返回类型、函数体和参数列表
一元操作符一个参数,二元操作符两个参数
成为类成员的操作符重载第一个参数被默认为this,所以参数个数再减一
只有调用操作符()可以有参数默认值,其他都不可以
操作符重载函数或者是类成员,或者必须含有一个类类型的参数(所以你不能重载内置类型的操作符)
只能重载已经存在的操作符,不能创造新的操作符(废话)
重载操作符的优先级和结合律与默认的保持一致
是不是很啰嗦?在这里举个例子吧。
class Foo { friend Foo operator+(const Foo&, const Foo&); public: explicit Foo(int i):data(i){} private: int data; } Foo operator+(const Foo &left, const Foo &right) { return Foo(left.data + right.data); }
4.下面将各种操作符的重载列在如下表中:
操作符名称 | 函数名 | 返回值 | 参数列表 | 声明位置 | 其他说明 |
---|---|---|---|---|---|
输入输出操作符 | operator<< operator>> | stream对象的引用 (保证>>和<<可以连续使用) | stream &s, const Type &t (输入输出会改变流状态,所以引用不能为const) | 类外friend (因为第一个参数不能为this) | 输入操作符必须处理流失败 输出操作符则不需要 |
算数操作符 | operator+ operator- operator* operator/ %^!~&| | Type的临时对象 (与内置类型的行为保持一致) | const Type &t1, const Type &t2 | 类外friend | 推荐连同对应的复合运算符 一起定义,在内部可以使用 定义好的复合运算符来实现 对应的外部运算符 |
关系运算符 | operator== operator!= operator< <= > >= | bool | const Type &t1, const Type &t2 | 类外friend | 推荐成对定义,例如:定义 了==后把!=也定义了,并用 ==实现!=;推荐定义<,因 为这样可以在更多的STL容 器中使用;最好能够保障传 递性 |
赋值运算符 | operator= | Type & (返回左侧对象的引用) | const Type & (拷贝赋值) Type && (移动赋值) 以及其他各种类型 | 类member (因为要返回左侧对象的引用) | 只建议定义拷贝、移动以及 initializer_list版本的,其他 类型的版本容易让人费解 |
复合赋值运算符 | operator+= operator-= operator*= operator/= %=^=&=|= <<= >>= | Type & | const Type & 以及其他各种类型 | 推荐类member | 不建议定义奇怪的,定以后 建议同时定义对应的运算 |
下标运算符 | operator[] | 类内对象类型的引用 | size_t | 类member (因为要返回类内对象的引用) | 建议同时定义const与非 const版本,来保证const 对象也可以使用 |
前置递增递减 | operator++ operator-- | Type & | 无 | 类member (因为改变了对象本身) | 定义前置的同时建议也定 义后置版本 |
后置递增递减 | operator++ operator-- | Type的临时对象 (递增递减前的拷贝) | int (注意,int只是为了与前置版本区分,从来不用) | 类member | 定义后置的同时建议也定 义前置版本 |
成员访问运算符 | operator* operator-> | Type & Type * | 无 | 类member | 推荐成对定义:注意保证-> 的语义不变 |
函数调用运算符 | operator() | 任意 | 任意 | 类member (不然就不是函数对象了) | 可以有多个重载版本 |
类型转换运算符 | operator type | type | 无 | 类member | 注意类型转换的二义性 |
class Foo{ public: int operator() (int a, int b) const { return a - b; } }; Foo minus; //函数对象 int c = minus(5, 4); //c = 1而lambda表达式的背后,由编译器生成了一个重载了operator()的临时类的临时对象。值捕获的局部变量会被临时类的构造函数“拷贝”到类中;非mutable标记的lambda表达式对应的operator()是const的(所以不能修改捕获的变量);引用捕获的局部变量就不需要这一“拷贝”过程,而直接被编译器使用。lambda表达式和函数对象通常与泛型算法合作完成任务。
6.function类型:在c++当中,以下四种类型的对象是可以被调用的。
函数
函数指针
lambda表达式
可调用对象
在混合使用它们的时候,相当的不方便,因为它们是四种不同类型的对象。为了解决这一问题,c++11中新增了function类型模板,以调用形式(“返回值-参数列表”)为Type,可以兼容以上全部类型,让它们像同一个类型的对象一样工作。
int add(int a, int b) { return a + b; } int (*add_ptr) (int, int) = add; auto add_lambda = [](int a, int b) { return a + b; } class ADD { int operator() (int a, int b) { return a + b; } }; ADD add_object; function<int(int, int)> f1 = add; function<int(int, int)> f2 = add_ptr; function<int(int, int)> f3 = add_lambda; function<int(int, int)> f4 = add_object;
注意:不能将重载函数直接放入function中,需要用函数指针明确指明或者lambda临时包装一下(这方法太经典了)。
7.显式类型转换符explicit:在c++11中,新增了显式类型转换符,用来阻止编译器利用定义好的类型转换符来进行隐式类型转换。增加了explicit的类型转换符必须显式调用类型转换才可以(static_cast等)。
class Foo { public: Foo (int i):data(i){} explicit operator int () {return data;} private: int data; }; Foo f(1); int a = 2 + f; //隐式转换,错误 int b = 2 + static_cast<int>(f); //ok,显式转换注意:当表达式被当做条件处理时(if/while/do-while/for/问号表达式/&&/||/!),编译器会隐式的执行显式类型转换。
8.类型转换的best practice:除了定义显式bool类型转换符之外,不要定义其他的类型转换。
相关文章推荐
- C++ Primer阅读心得(第八章、第九章)
- C++ Primer阅读心得(第一章、第二章上)
- C++ Primer阅读心得(第十章、第十一章)
- C++ Primer阅读心得(第六章)
- C++ Primer阅读心得(第十五章)
- C++ Primer阅读心得(第三章)
- C++ Primer阅读心得(第十六章)
- C++ Primer阅读心得(第七章)
- C++ Primer阅读心得(第十二章)
- C++ primer阅读心得(第十三章)
- C++ Primer阅读心得(第四章、第五章)
- C++ Primer阅读心得(第二章下)
- 《卓有成效的管理者》阅读心得
- zz spru976阅读心得
- C++ Primer 第二遍阅读笔记(第三章)
- C++ Primer 第二遍阅读笔记(第十二章)
- Struts源码阅读心得之logic:Iterator篇
- c++ primer阅读笔记-15章-6
- PBRT阅读:第十四章 蒙特卡罗积分I:基本概念
- 利用OpenMCU加深对H.323协议的理解——H.323协议阅读心得(2)