• effictive c++


    c++条款

    num 1:尽量以const enum inline替换#define

       1)对于单纯常量,最好以const对象或enums替换#defines

       2)对于形似函数的宏,最好改用inline函数替换#define

    num 2:尽可能使用const

       1)将某些东西声明为const可帮助编译器侦测出错误用法

       2)当const  non-const 成员函数有着实质等价的实现时,令nono-const调用const版本可避免重复。

        eg:

          class TextBlock {

          public:

            const char& operator[](std::size_t position) const {

              return text[position];

            }

            char& operator[](std::size_t position) {

              return   const_cast<char&>(static_cast<const TextBlock&>(*this)[position]);

              //从原始TextBlock转换为const TextBlock,调用const operator[],将const char& 转换为char&.

            }

          };

    num 3:确定对象被使用前已被初始化

       1)对内置型对象进行手工初始化,因为c++不保证初始化它们

       2)构造函数最好使用成员初始化列表,其排列次序和它们在class中的声明次序相同

       3)以local static对象替换non local static对象

        当某编译单元内的non-local static对象的初始化动作使用另一个编译单元内的某个nono-local static对象,但所用对象可能尚未初始化。----将non-local static对象搬到自己的专属函数内,这些函数返回一个reference指向它所含的对象。然后用户调用这些函数。保证对象已被初始化

    二:构造/析构/赋值运算

    num 1:编译器可暗自创建4个成员函数

        当class内含reference成员或const成员,必须自己定义赋值操作符

    num 2:若不想使用编译器自动生成的函数,就应该明确拒绝

        1)所有编译器产出的函数都是public:可将不想使用的函数放入private且只声明不实现

    num 3:为多态基类声明virtual析构函数

        1)当基类的析构函数为非virtual,是错误做法。如string作为基类

        2)希望class成为抽象的class为其声明pure virtual 析构函数。virtual ~AWOV() = 0;

        3)带多态性质的基类应声明一个virtual析构函数。若class带有任何virtual函数,它就应该拥有一个virtual析构函数

        4)class的设计目的若不是作为基类使用或不是为了具备多态性质,就不应该声明virtual析构函数

    num 4:别让异常逃离析构函数

        1)析构函数绝对不要吐出异常。析构函数应该捕捉任何异常并吞下它们或结束异常

        2)若客户需要对某个操作函数运行期间抛出的异常做出反应,那class应该提供一个普通函数执行该操作

    num 5:绝不在构造析构中调用virtual函数

    num 6:令operator=返回一个reference to *this

    num 7:在operator=中处理自我赋值

        eg:Widget&  Widget::operator=(const Widget& rhs)

          {  if(*this == rhs) return *this;    delete pb;  pb = new Bitmap(*rhs.pb); return *this; 

            //2:Bitmap* pOrig = pb; pb = new Bitmap(*rhs.pb); delete pOrig; return *this;

           }

    num 8:复制对象时勿忘其每一个成分

       1)确保复制“对象内的所有成员变量及所有基类成分    

       2)不要常识以某个copy函数实现另一个copy函数。应该将共同机能放进第三个函数,并有两个copy函数共同调用

    三:资源管理

    num 1:以对象管理资源

       1)在构造函数中获得资源,在析构函数中释放资源

       2)使用shared_ptr  auto_ptr管理资源。最好使用shared_ptr---计数指针,当引用计数为0时释放对象。当shared_ptr  auto_ptr其析构函数调用delete,因此不能与数组相关

    num 2:在资源管理类中小心coping行为???

    num 3:在资源管理类中提供对原始资源的访问???

    num 4:成对使用new delete时要采取相同形式

    num 5:以独立语句将newed对象置入智能指针

        eg:shared_ptr<Widget> pw(new Widget);

          processWidget(pw,priority());

    四:设计与声明

    num 1:让接口容易被使用,不易被误用

    num 2:设计class犹如设计type

       1)新type的对象应该如何被创建和销毁?

       2)对象的初始化和对象的赋值该有什么样的差别?

       3)新typw的对象如果被passed by value,意味着什么?copy 构造函数用来定义一个type的passed by value

       4)什么是新type的合法值?

       5)你的新type需要配合某个继承图系吗?

       6)你的新type需要什么样的转换?

       7)什么样的操作符和函数对此新type而言是合理的?

       8)什么样的标准函数应该驳回?那些必须声明为private

       9)什么是新type的未声明接口?

       10)谁该取用新的type成员?

       11)是否真的需要一个新type?

    num 3:以引用传递代替值传递

       1)引用传递更高效

       2)该规则并不适合内置类型以及STL的迭代器和函数对象。值传递更适合

    num 4:必须返回对象时,别妄想返回其reference??

    num 5:将成员变量声明为private

       1)protected并不比public更具封装性

    num 6:宁以non-member non-friend 替换member函数

    num 7:若所有参数皆需类型转换,请为此采用non-member 函数

        如算数混合运算,可以使用非成员函数或友元函数进行类型转换

    num 8:考虑写出一个不抛异常的swap函数

       1)以指针指向一个对象,内含真正数据。当要置换两个对象值,唯一需要做的就是置换其指针---具体实践是将std::swap针对对象特化。

        eg:class Widget {

          public:  void swap(Widget& other)  { using std:swap;  swap(pImpl,other.pImpl); }

          };

        namespace  std {

         template<>

         void swap<Widget>(Widget& a,Widget& b)  { a.swap(b);   }

        }

       2)偏特化只对类模板有用

       3)当std:swap对类型效率不高时,提供一个swap成员函数

       4)当提供一个member swap,也提供一个非member swap来调用

      

    五:实现

    num 1:尽可能延迟变量定义式的出现时间

    num 2:尽量少做转型

    num 3:避免返回handles(指针、引用、迭代器)指向对象内部成分

    num 4:为异常安全而努力是值得的

    num 5:透彻了解inlining

    num 6:将文件间的编译依存关系降至最低

       1)相依于声明式,不要相依于定义式

    六:继承与面向对象设计

    num 1:确定public继承是is_a关系

    num 2:避免遮掩继承而来的名称

    num 3:区分接口继承和实现继承

       1)public继承下,子类总是继承父类接口

       2)pure  virtual函数只具体指定接口继承

       3)非纯虚函数具体指定接口继承及缺省实现继承

       4)非虚函数指定接口继承和强制实现继承

    num 4:考虑virtual函数以外的其他选择

    num 5:绝不重新定义继承而来的non-virtual函数

    num 6:绝不重新定义继承而来的缺省参数值(默认参数值)

    num 7:明智而审慎使用private继承

    七:模板与泛型编程

    num 1:了解隐式接口与编译期多态

       1)class与template都支持接口和多态

       2)对class而言接口是显式,以函数签名为中心,多态通过虚函数发生与运行期

       3)对template而言,接口是隐式,有效表达式展现。多态通过具现化与函数重载解析发生于编译期

    num 2:了解typename双重意义

       1)使用template标识嵌套从属类型名称,但不能在基类列表或成员初始化列表内以他作为基类修饰符

    num 3:学会处理模板化基类内的名称??

    num 4:将与参数无关的代码抽离template

       1)template生成多个class和函数,任何template代码都不该与某个参数产生相依关系

       

        

             

  • 相关阅读:
    public static void Invoke (Action action)
    C#编写WIN32系统托盘程序
    C#的互操作性:缓冲区、结构、指针
    SQLServer异步调用,批量复制
    Python体验(10)-图形界面之计算器
    Python体验(09)-图形界面之Pannel和Sizer
    Python体验(08)-图形界面之工具栏和状态栏
    Python体验(07)-图形界面之菜单
    C#利用WIN32实现按键注册
    Javascript猜数字游戏
  • 原文地址:https://www.cnblogs.com/pengtangtang/p/12921386.html
Copyright © 2020-2023  润新知