亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定

將文件間的編譯依賴降到最低

標簽:
Java

问题描述

// file : Person.hpp#include <string>#include "date.h"#include "address.h"class Person{
    public:
    Person( const std::string& name, const Date& birthday, const Address& addr );    std::string name() const;    std::string birthData() const;    std::string address() const;
    ...    private:    std::string theName;
    Date theBirthDate;
    Address theAddress;
}

当 Person.hpp 修改时,会导致依赖该文件的源码都要重新编译,导致漫长的编译时间。

问题表现为,头文件包含和依赖

如上所示, Person.hpp 中包含文件 date.h 和 address.h 即 Person.hpp 依赖于这两个文件,并递归依赖于这两个文件依赖的文件,当这两个文件及其依赖的文件有任何修改时,包含 Person.hpp 的源码文件都要重新编译。

解决方式 1a:前向声明

// file : Person.hpp #include <string>class Date;class Address; // 引入前置声明, 去掉头文件的包含 "date.h" 和 "address.h" (不正确)class Person{
    public:
    Person( const std::string& name, const Date& birthday, const Address& addr );    std::string name() const;    std::string birthData() const;    std::string address() const;
    ...    private:    std::string theName;
    Date theBirthDate;
    Address theAddress;
}// 上述声明在声明 Person 对象时,会导致问题,如下所示int main(){    int x;    Person p( params ); // 创建对象时,编译器必须能够指导 Person 类型占用的内存大小,
                        // 仅前向声明无法提供足够的 Date 和 Address 的类型信息
                        // 与此类比的是,python 和 java 等语言,Person 中的如 theBirthDate 变量都是指针。
                        // 在使用时需要经过一次指针的引用,增加部分内存,损失些许性能,极大降低了文件的耦合}

解决方式 1b:前向声明配合 pimpl (pointer to implemention)

// PersonFwd.hpp // 声明式和定义式两个文件,怪怪的, 据说是为了模板struct PersonImpl;class Date;class Address; // 引入前置声明, 去掉头文件的包含 "date.h" 和 "address.h"http:// file : Person.hpp #include "PersonFwd.hpp"#include <string>#include <memory.h>class Person{
    public:
    Person( const std::string& name, const Date& birthday, const Address& addr );    std::string name() const;    std::string birthData() const;    std::string address() const;
    ...    private:    std::shared_ptr<PersonImpl> pImpl; // 指针指向实现物}// file : PersonImpl.hpp#include "date.h"#include "address.h"struct PersonImpl{
    std::string theName;
    Date theBirthDate;
    Address theAddress;
    PersonImpl( const std::string& name, const Date& birthday, const Address& addr ):
        theName( name ), theBirthDate( birthday), theAddress( addr )
    { }
}

优点

  • Person.hpp 实现了与之前依赖的头文件 date.h 和 address.h 及由此递归依赖的文件的解耦,可是改为 PerImpl.h依赖上述文件,只是该依赖不会继续向上传递;

  • Person 类型的声明 Person.hpp 及实现 PersonImpl.h 的解耦, 修改 Person 类实现时,只需要修改 PersonImpl.h 即可,不会影响使用 Person 类的文件。

代价

  • 成员函数必须通过 implemention pointer 取得对象数据,访问是间接的,且增加了 implemetion pointer 的指针的内存,增加了动态内存分配的管理开销,及 bad_alloc 异常的处理难度。

解决方式 2:abstract base class

// file : Person.hpp #include <string>#include <memory.h>class Person{
    public:    virtual ~Person();    virtual std::string name() const = 0;    virtual std::string birthData() const = 0;    virtual std::string address() const = 0;    // 可以使用工厂方法创建对象,static member function
    static std::shared_ptr<Person> create( const std::string& name, const Date& birthday, const Address& addr )
    {        // 返回 ptr -> derived class obj。
        // 有多个 derived class 时,入参中加入 derived class 的id, 字符串或者枚举,内部用 switch 返回对应类型对象
    }    // 也可以使用 virtual 构造函数
    virtual Person()
    {
    }
    ...
}// 客户必须以 Person 的 pointers 和 reference 编写程序,并指向 Person 的 derived class 对象。 // file : PersonImpl.hpp#include "date.h"#include "address.h"#include "Person.hpp"class PersonImpl : public Person
{private:    std::string theName;
    Date theBirthDate;
    Address theAddress;public:
    PersonImpl( const std::string& name, const Date& birthday, const Address& addr ):
        theName( name ), theBirthDate( birthday), theAddress( addr )
    { }    std::string name() const { ... };    std::string birthData() const { ... };    std::string address() const { ... };
}

其他解决方案

  • P143,编译依赖最小化的本质,尽量让头文件自我满足,万一做不到就尽量依赖其他文件的声明式,而非定义式;

  • P143,如果使用 object references 或 pointer 可以完成任务,就不要使用 object value, references 和 pointer 可以借助前向声明完成编译,object value 必须包含头文件。

  • P143,尽量以 class 声明式代替 class 定义式,特别是在声明函数时,可以使用前向声明完成编译,不需要一定包含头文件, by value 传参除外,必须要包含头文件。



作者:呆呆的张先生
链接:https://www.jianshu.com/p/5e0bd47876a1


點擊查看更多內容
TA 點贊

若覺得本文不錯,就分享一下吧!

評論

作者其他優質文章

正在加載中
  • 推薦
  • 評論
  • 收藏
  • 共同學習,寫下你的評論
感謝您的支持,我會繼續努力的~
掃碼打賞,你說多少就多少
贊賞金額會直接到老師賬戶
支付方式
打開微信掃一掃,即可進行掃碼打賞哦
今天注冊有機會得

100積分直接送

付費專欄免費學

大額優惠券免費領

立即參與 放棄機會
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號

舉報

0/150
提交
取消