zoukankan      html  css  js  c++  java
  • 《Effective C++》实现:条款26-条款31

    条款26:尽可能延后变量定义式的出现时间

    • C++推荐在使用对象前才定义对象(调用构造函数赋初值)
    • 只在循环中使用的变量定义在循环内部(除非"赋值"成本低于"构造+析构"成本)

    条款27:尽量少做转型动作

    • 旧式风格转型
      • C风格转型 ((T)expression)
      • 函数风格转型 (T(expression))
    • C++四种新式转型(new-style 或 C++-style cases)
      • const_cast(expression) 移除对象常量性(cast away the constness)
      • dynamic_cast(expression) 安全向下转型(safe downcasing)
      • reinterpret_cast(expression) 低级转型
      • static_cast(expression) 强迫隐式转型(implicit conversions)
    • 尽量避免转型(特别是dynamic_cast)
    #include <iostream>
    #include <string>
    #include <memory>
    
    using namespace std;
    
    class base {
    public:
        virtual void type() {cout << "base" << endl;}
    };
    
    class drive : public base {
    public:
        drive( double d) : dou(d) {}
        virtual void type() {cout << "drive" << endl;}
    
        void show() {
            cout << dou << endl;
        }
    
    private:
        double dou;
    };
    
    int main() {
        shared_ptr<base> b = shared_ptr<base>(new drive(1.2));
        shared_ptr<drive> d = dynamic_pointer_cast<drive>(b);
        d->show();
    }
    

    改写成

    #include <iostream>
    #include <string>
    #include <memory>
    
    using namespace std;
    
    class base {
    public:
        virtual void type() {cout << "base" << endl;}
        virtual void show() {}
    };
    
    class drive : public base {
    public:
        drive( double d) : dou(d) {}
        virtual void type() {cout << "drive" << endl;}
    
        virtual void show() {
            cout << dou << endl;
        }
    
    private:
        double dou;
    };
    
    int main() {
        shared_ptr<base> b = shared_ptr<base>(new drive(1.2));
        b->show();
    }
    
    
    • 使用C++新式转型,而非使用旧式转型

    条款28:避免返回handles指向对象内部成分

    • 避免返回指向对象内部成员的handles(包括references,指针,迭代器)

    条款29:为“异常安全”而努力是值得的

    • "异常安全函数"承诺即使发生异常也不会有资源泄漏或数据结构的破坏。
      • 基本保证:如果抛出异常,程序仍然保持有效状态
      • 强烈保证:如果抛出异常,程序状态恢复到调用前
      • 不抛异常:内置类型的操作就绝不会抛出异常

    条款30:透彻了解inlining的里里外外

    • inline的申请方式
      • 隐喻方式——将函数定义于class内(包括定义域class的友元函数)
      • 声明方式——函数定义式前加关键字inline
    • inline只是个申请,编译器可以忽略
      • 大部分编译器拒绝inline太过复杂的函数(带有循环或递归的函数)
      • 所有调用virtual函数(除非是平淡无奇的)
    • 不要把构造函数和析构函数申请为inline
    • inline应该设置在小型,频繁调用的函数身上

    条款31:将文件间的编译依存关系降至最低

    • 用 "声明的依赖" 替换 "定义的依赖"(让头文件尽可能自我满足,如果做不到就和其他文件的声明式相依)
      • 使用object references 或 object pointers 可以完成的任务,就不要使用objects 
      • 如果能够,尽量以class的声明式替换class的定义式
      • 为声明式提供不同的头文件
    • Handle classes
      • Handler Classes中将变量换成变量的地址(指针),头文件只给出具体的class xxx的声明,而在cpp里面才c具体lass的实现
      • 由此Handler Classes只暴露出接口,并隐藏数据结构
    //Person.h
    #ifndef PERSON_H
    #define PERSON_H
    #include <string>
    #include <memory>
    using namespace std;
    class PersonImp;
    class Person
    {
    public:
        Person(const string& na);
        string GetName() const;
    
    private:
        shared_ptr<PersonImp> MemberImp;
    };
    
    #endif // PERSON_H
    
    //Person.cpp
    #include "Person.h"
    class PersonImp
    {
    public:
        PersonImp(string na) : Name(na){}
    
        string GetName() const {
                return Name;
        }
    private:
        string Name;
    };
    
    Person::Person(const string& na) : MemberImp(new PersonImp(na)) {
    }
    
    string Person::GetName() const
    {
        return MemberImp->GetName();
    }
    
    //main.cpp
    #include <iostream>
    #include <string>
    #include "Person.h"
    
    int main() {
       Person p("xiao ming");
       cout << p.GetName() << endl;
    }
    
    • Interface classes(抽象类)
      • 利用多态,在父类抽象类中定义接口,并利用静态函数(static creat)返回具体对象
      • 抽象类暴露接口,并隐藏数据结构等
    //Persion.cpp
    #include "Person.h"
    class RealPerson : public Person {
    public:
        RealPerson(const string& na) : name(na) {}
        virtual string GetName() const {
            return name;
        }
    
    private:
        string name;
    };
    
    shared_ptr<Person> Person::creat(const string &na) {
        return shared_ptr<Person>(new RealPerson(na));
    }
    
    //Person.h
    #ifndef PERSON_H
    #define PERSON_H
    #include <string>
    #include <memory>
    using namespace std;
    class Person
    {
    public:
        static shared_ptr<Person> creat(const string& na);
    
        virtual string GetName() const = 0;
    };
    
    #endif // PERSON_H
    
    //main.cpp
    #include <iostream>
    #include <string>
    #include "Person.h"
    
    int main() {
       shared_ptr<Person> p = Person::creat("xiaoming");
       cout << p->GetName() << endl;
    }
    
  • 相关阅读:
    char
    export和export default
    递归打印文件目录
    centso7 安装redmine
    sonar结合jenkins
    sonar安装
    gitlab+jenkins
    centos5 安装redmine
    elk安装最佳实践
    elk认证模块x-pack安装
  • 原文地址:https://www.cnblogs.com/narjaja/p/10187516.html
Copyright © 2011-2022 走看看