• Effective C++ 读书笔记(1828):类与函数之设计和声明


    类与函数的设计和声明

    看看作者思考问题的角度:

    对象如何产生和销毁: 构造析构、new和delete的重载

    对象的初始化和赋值:构造、拷贝构造、赋值重载

    新型别转换相关:合法值的规范检验、继承体系、是否隐式转换

    访问权限:public、protected、private如何设计

     

    Item18 -- 努力让接口完满且最小化

    1,KISS原则;2,头文件的重要性;

     

    Item19 -- 区分member functions, non-member functions和friend functions三者

    1,如果要实现虚函数,必须是member function
    2,让operator<<和operator>>成为non-members,如果还需要获取类的非公共成员变量,声明为friend。原因,如果是func为member,那么以后书写顺序应该是obj>>cin,obj<<cout,这样不符合习惯
    3,只有non-member才能在最左参数身上实施型别转换。如果需要对函数f的最左侧参数进行型别转换,那么f为non-function,如果还需要获取类的非公共成员变量,声明为frind。
    举例,operator *(Class &lhs, Class &rhs)这种声明,2*obj2的调用,需要对2进行型别转换(构造函数声明为explicit可以阻止隐式型别转换),这样就必须为non-member

    Item20 -- 避免将data members放在公开接口中

    Effective中举了三个原因,说明为什么不要放在公开接口中

    1. 一致性,以后对类对象的所有操作,均需要带(),也就是只能调用函数,不能获取变量
    2. 获取控制性,比如只读、可读可写、不处理,通过不同的函数实现
    3. 函数抽象性,提供一个借口,底层如何实现上层用户不用关心

    不过在实际编程中,很少人能够完全做到这点,毕竟需要自己花些时间来写get和set,暂时我也没找到自动生成get、set函数的方法,所以鱼与熊掌不可兼得,若想获得好处,就得费力写get、set了。

    Item21 -- 尽可能使用const

    1,*号在中间,前定内容后定针
    2,返回值用const修饰,说明返回值是只读的,不能修改
    3,函数后面用const修饰,说明该函数不能修改任何变量。函数可以据此进行重载,有const的函数被const对象调用,没有const的函数被非const对象调用
    const的真正意义是什么?不变性,具体的体现有两种说法:A, bitwise. B, conceptual,A说法对位进行比较,如果没有修改则认为是不变的。B从概念层面进行判断,即使底层有修改,但对上层概念来讲是不变的,那就是不变的。但是C++语言只支持A,所以为了应付B,引入mutable修饰词,用来修饰上层概念不变,但是底层要修改的底层变量。
    4,const可以通过const_cast取消常量性

    Item22 -- 尽量使用pass-by-reference,少用pass-by-value

    1. C语言里面都是传值
    2. 传值成本比较大,会调用对象的拷贝构造,如果类比较复杂,则会创建和析构更多的对象
    3. 传引用会避免切割问题。Func(base&) 和Func(base)两种函数声明,内部调用f()虚函数,如果传递个derived对象,则传引用会调用derived.f(),而传值则会切割而调用base.f()

    Item23 -- 当你必须回传object时,不要尝试传回reference

    用重载乘法举例

    Inline const Rational Operator*( const Rational& lhs, const Rational & rhs)

    {

    return Rational(lhs.n*rhs.n, lhs.d*rhs.d);

    }

    传回的是value,如果传回reference的话,内部变量析构之后,引用没有真正的对象

    Item24 -- 在函数重载和参数缺省化之间,谨慎选择

    void g(int x=0);

    g();

    g(10);

    void f(); void f(int x);

    f();

    f(10);

    两种方式要谨慎选择,避免出现模棱两可的情况

    Item25 -- 避免对指针型别和数值型别进行重载

    void f(int x);

    void f(string *ps);

    f(0)

    0的存在会对指针和数值造成模棱两可,所以要坚决避免针对指针和数值进行重载

    Item26 -- 防卫潜伏的ambiguity(模棱两可)状态

    C++有一个哲学信仰,它相信潜在的模棱两可状态不是一种错误,但是对程序员来讲,将所有问题放到运行后发现就是一种灾难。所以程序员应该避免模棱两可。
    类的转换,一是拷贝构造方式可以隐式转换,一是operator Class()方式,当需要型别转换时,就会有模棱两可

    1. 语言标准转换,6.02可以转换成int也可以转换成char
    2. 多继承也是如此

    当遇到模棱两可情况时,程序员应该显式的说明采用哪种方式。

    Item27 -- 如果不想使用编译器暗自产生的member functions,就应该明白拒绝它

    1. 使用private修饰防止公开调用
    2. 不定义防止friend等调用

    private:

    Array& operator=(const Array &rhs);(注意这里;表示不定义)

     

    Item28 -- 尝试切割global namespace

    namespace name1{

    }

    using namespace name1;

    最好每个人都以自己姓名为name,进行分割,这样可以类似Java中的包的概念

  • 相关阅读:
    ATM+购物车
    subprocess,re,logging模块
    json,pickle,collections,openpyxl模块
    time,datatime,random,os,sys,hashlib模块
    1.内置函数剩余部分 map reduce filter 2.函数递归 3.模块
    生成器,面向过程编程,三元表达式,列表生成式,生成器表达式,匿名函数,内置函数
    Ajax数据对接出问题了?ThingJS解决方法在这里
    测试
    简单低成本的物联网开发平台-ThingJS
    用ThingJS之CityBuilder快搭3D场景,可视化开发必备
  • 原文地址:https://www.cnblogs.com/liuchen/p/1585666.html
Copyright © 2020-2023  润新知