款31:将文件间的编译依存关系降到最低
2015-09-17 03:42
375 查看
/*条款31:将文件间的编译依存关系降到最低*/ #include<iostream> #include<string>//如果不加上下面三行会编译不过,然而这就是形成编译依存关系的源头 #include"data.h" #include"address.h" using namespace std; class Person { public: /* namespace std{ 但这是不正确,而是一个basic_string<char>的typedef class string; }所以你的接口设计应该避免标准程序库中的#include那部分 class Date; class Address;//前置声明 编译器必须需要声明的原因在于它先要分配内存,而前提是必须知道对象的大小,内置类型倒也无所谓 */ Person(const std::string&name, const Date&birthday, const Address&addr) {} std::string name()const{} std::string birthDate()const{} std::string address()const{} private: std::string theName; Date theBirthDate;//如果这三行的修改,编译的话,会发现整个世界都被重新编译和连接了 Address the Address; }; //--------------所以可以将对象实现细目隐藏于一个指针背后 #include<string>//s标准库组件不该被前置声明 #include<memory> class PersonImpl;//Person实现类的前置声明 class Date; //Person接口用到的类的前置声明 class Address; class Person { public: Person(const string &name, const Date&birthday, const Address&addr) {} string name()const; string birthDate()const; string address()const; private: std::str1::shared_ptr<PersonImpl>pImpl;//指向实现物 //这样Person的客户就完全与Date Address以及Persons的实现细目分离了 //实现了接口与实现分离 //这里的关键在于声明的依存性替换了定义的依存性,这正是编译依存最小化的本质 /* 设计策略: 1 如果使用obj ref或obj ptr可以未完成任务,就不要使用obj 但如果定义obj 就需要用到定义式了 2 如果能,尽量以类声明式替换类定义式 当你声明一个函数用到某个类,你不需要定义,给个前置声明 值传递也一样 3 为声明式和定义式提供不同的头文件 */ }; //-----Person两个成员函数的实现 #include "Person.h"//实现person 必须包含它的定义式 #include"personImpl.h"//必须包含它的定义式,否则无法调用它的成员函数 personImpl有着和person完全相同的成员函数,两者接口完成相同 Person::Person(const。。。) :pIml(new PersonImpl(name, birday, addr)) {} std::string Person name()const { return pImpl->name(); } std::string Person::name()const { return Pimpl->name(); } //--另一个制作Handle class 的办法 是让person成为抽象基类,称为接口类 //它的目的是一一描述子类的接口,它通常不带成员变量,也没有构造函数,只有虚析构以及一组纯虚函数,用来 叙述整个接口 class Person { public: virtual ~Person(); virtual std::string name()const = 0; virtual std::string birthDate()const = 0; virtual std::string address()const = 0; //.. static std::tr1::shared_ptr<Person> create(const std::string&name, const Date&birthday, const Address&addr); }; class RealPerson :public Person { public: //..对应具体接口规格的实现 }; //Handle classes interface classes 解除了接口与实现之间的耦合关系,从而降低了文件间的编译依存性 //Handle类的受动态内存分配与释放而来的额外开销,interface类的virtual的开销这些带来的影响要于耦合带来的影响做一个权衡 // 程序库头文件应以完全且仅有声明式的形式存在,这种做法不论是否涉及模板都适用 int main() { share_ptr<Person>pp(Person::create(name, dateofBirth, address)); cout << pp->name() << "was born on" << pp->birthDate() << "adnd now lives at" << pp->address(); //... system("pause"); return 0; }
相关文章推荐
- 课下参考二 安装Linux系统初步
- 课下参考五 linux的ssh服务实现多用户登录linux系统--windows客户端篇
- java网络编程【精简篇】
- Single Number II
- 从Activity的启动细窥BinderIPC(1)
- 课下参考四 配置并使用ssh登录LINUX的主机--windows篇
- 「LintCode」java字符串練習四──anagrams
- CSS样式小总结
- 《女士品茶》与统计检验
- 浅谈Linux中的信号处理机制(一)
- [CareerCup] 9.1 Climbing Staircase 爬楼梯
- cf#320 Div.2 Problem D "Or" Game
- 二叉树重建及遍历
- *LeetCode-Remove Linked List Elements
- git-cola
- Codeforces #320(div2)
- ubuntu彻底清除Apache+Mysql+PHP
- HTML&CSS Learning Notes 5
- form 提交
- Leetcode Binary Tree Paths