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

本文详细阐述了如何通过接口与实现分离来减少C++程序中文件间的编译依赖。通过前置声明而非定义,避免引入不必要的头文件依赖,以及使用智能指针等现代C++特性,实现接口与实现的解耦,从而提高代码的可维护性和模块化。重点展示了如何利用`std::shared_ptr`和抽象基类`interface classes`来降低编译依存性,同时保持代码的灵活性和效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

/*条款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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值