Skip to content

Latest commit

 

History

History
158 lines (129 loc) · 3.84 KB

14重载运算与类型转换.md

File metadata and controls

158 lines (129 loc) · 3.84 KB

cppp第十四章 阅读笔记

1.符号重载的本质

特殊名字的函数

2.运算符函数

或者含有一个类类型参数
或者是类的成员(就会含有隐式this指针)

3.谁不能被重载

[ "::", ".*", ".", " ? : " ]

4.谁不应该被重载

逗号/取地址/逻辑与/逻辑或

5.是否应该以成员方式重载

  • 赋值/下标/调用/成员访问 必成员

  • 复合赋值 大概率成员

  • 改变状态/密切相关 大概率成员

  • 有对称性的运算符 通常非成员

    对称性举例:char* 与 string ,加号运算符 若+定义为成员,则默认string为第一位。

6.一些建议

  • 建议算数运算符用复合赋值运算符实现 (+ 调用 +=)
  • 建议不等判断调用相等判断 (!= 调用 ==)
  • 建议下标运算符定义const引用和非const引用两个版本
  • 后置自增/自减可以用前置来实现

7.有关成员访问运算符->

不那么直观。
对于内置指针和自定义类型有不同的解释方式
    ptr->func();
    //to
    (*ptr).func();

    myClass->func();
    //to
    (myClass.operator->())->func();
综上,自定义类的成员访问运算符最后应返回一个内置指针
当然你也可以返回一个定义了成员访问运算符的对象
然后递归的执行这个操作

8.易混相关的定义

名称 表示 定义
前置自增 ++myClass; MyClass& operator++();
后置自增 myClass++; MyClass& operator++(int = 0);
//一般不用这个0,由编译器提供
前置自减 --myClass; MyClass& operator--();
后置自减 myClass--; MyClass& operator--(int = 0);

9.lamda的实质

看起来是匿名函数
实质编译器帮你做的是产生一个匿名类的匿名对象
这个匿名类的构造器对应了捕获列表[...]
重载operator()对应了参数列表(...)和函数体{...}

10.标准库的可执行对象

名称 含义
plus<>
minus<>
multiplies<>
divides<>
modulus<>
negate<>
equal_to<>
not_equal_to<> 不等
greater<> 大于
greater_equal<> 大于等于
less<> 小于
less_equal<> 小于等于
logical_and<>
logical_or<>
logical_not<>

11.可调用与function

可调用对象:函数/函数指针/lambda/bind创建的/仿函数
他们可以有相同的**调用形式**
如 int(double, int)

我们创建函数表时,可以写作如下形式
map<string,int(*)(double, int)> 
也可以写作如下
map<string,fucnction<int(double, int)>>

12.类型转换运算符

  • 本类转为其他类时用到的运算符
  • 通常为const
  • 不用(也不能)显式指定返回类型
  • 必须作为成员函数
  • 不能有参数
  • 需要时加explicit来避免隐式调用
    (注意:用作条件时explicit无效)
    (注意:用作条件时explicit无效)
    (注意:用作条件时explicit无效)
class MyClass{
    int val;
    operator int() const {
        return val;
    };
};

13.类型转换产生的二义性

//def:
class A{
    A(B);
};
class B{
    operator A() const {...};
};
void func(A);

//call:
func(B());

解决方法:

  • 去的路和回来的路最好只给一条
  • 类似的路(int/double)最好只给一条
  • 如果只能都给,那调用的时候请显示调用

-1.成员指针运算符

偏移型指针,记录了类中某成员的地址偏移。
使用的时候需要提供一个对象。
//我真没见过有人用这沙雕东西
class MyClass{
public:
    int val;
    void setVal(int v){
        val = v;
    };
};


MyClass myClass;
shared_ptr<MyClass> sptrM = make_shared<MyClass>();

auto ep = &MyClass::val;
//int MyClass::*ep = &MyClass::val;
auto fp = &MyClass::setVal;
//void (MyClass::*fp)(int) = &MyClass::setVal;
    
    
myClass.*ep = 666;
(myClass.*fp)(777);

sptrM.get()->*ep = 666;
(sptrM.get()->*fp)(777);