C++箴言:最小化文件之间的编译依赖

C++箴言:最小化文件之间的编译依赖,第1张

C++箴言:最小化文件之间的编译依赖,第2张

你进入你的程序,对一个类的实现做细微的改变。请注意,它不是一个类的接口,它只是一个实现,只是一些私有的东西。然后你重建这个程序。预计该任务只需几秒钟。毕竟只改了一个班。你在Build上点击或者输入make(或者其他等价行为),然后你就懵了,然后抑郁了,就像你突然意识到整个世界都被重新编译连接了一样!发生这种事你不讨厌吗?

问题是C++没有很好地将接口从实现中剥离出来。一个类定义不仅指定了一个类的接口,而且有相当数量的实现细节。例如:

class Person {
public:
Person(常量std::string& name,常量日期&生日,常量地址& addr);
STD::string name()const;
STD::string birth date()const;
STD::string address()const;
...

private:
STD::string theName;//实现细节
Date the birthdate;//实现细节
Address地址;//实现细节
};

在这里,如果不访问Person的实现所使用的类的定义,即字符串、日期和地址,Person类就无法编译。这样的定义通常是通过#include指令提供的,因此在定义Person类的文件中,您可能会发现类似这样的内容:

# include
# include " date . h "
# include " address . h "

不幸的是,这在定义Person的文件和这些头文件之间建立了编译依赖关系。如果这些头文件中的一些已经改变,或者这些头文件所依赖的文件已经改变,那么包含Person类的文件必须重新编译,就像使用Person的文件一样。这样的级联编译依赖给项目带来了无数的麻烦。

也许你想知道为什么C++坚持把一个类的实现细节放在类定义里。比如为什么不能这样定义Person,单独指定这个类的实现细节?

命名空间std {
类字符串;//转发声明(一个不正确的
} // one -见下文)

上课日期;//转发声明
类地址;//向前声明

class Person {
public:
Person(常量std::string& name,常量日期&生日,常量地址& addr);
STD::string name()const;
STD::string birth date()const;
STD::string address()const;
...
};

如果这是可行的,只有当类的接口改变时,Person的客户必须重新编译。

这个想法有两个问题。第一,string不是类,它是typedef(对于basic_string)。因此,字符串的前向声明是不正确的。的正确前向声明要复杂得多,因为它包括附加模板。但是,这没有关系,因为您不应该试图手动声明标准库的各个部分。相反,只要使用适当的#includes,让它去做就行了。标准头文件不太可能成为编译的瓶颈,尤其是当您的构建环境允许您使用预编译头文件时。如果解析标准头文件真的成了问题。也许你需要改变你的界面设计来避免使用导致不受欢迎的#includes的标准库部件。

第二个(也是更重要的)困难是,所有声明为forward的东西都必须让编译器在编译时知道其对象的大小。考虑:

int main()
{
int x;//定义int

人p(参数);//定义一个人
...
}

位律师回复
DABAN RP主题是一个优秀的主题,极致后台体验,无插件,集成会员系统
白度搜_经验知识百科全书 » C++箴言:最小化文件之间的编译依赖

0条评论

发表评论

提供最优质的资源集合

立即查看 了解详情