2016-03-15 95 views
0

创建由其他类组成的类时,是否值得通过使用指针而不是值来减少依赖关系(从而减少编译时间)?应该使用指针来减少头依赖关系吗?

例如,以下使用值。

// ThingId.hpp 
class ThingId 
{ 
    // ... 
}; 

// Thing.hpp 
#include "ThingId.hpp" 
class Thing 
{ 
public: 
    Thing(const ThingId& thingId); 
private: 
    ThingId thingId_; 
}; 

// Thing.cpp 
#include "Thing.hpp" 
Thing::Thing(const ThingId& thingId) : 
    thingId_(thingId) {} 

但是,下面的修改版本使用指针。

// ThingId.hpp 
class ThingId 
{ 
    // ... 
}; 

// Thing.hpp 
class ThingId; 
class Thing 
{ 
public: 
    Thing(const ThingId& thingId); 
private: 
    ThingId* thingId_; 
}; 

// Thing.cpp 
#include "ThingId.hpp" 
#include "Thing.hpp" 
Thing::Thing(const ThingId& thingId) : 
    thingId_(new ThingId(thingId)) {} 

我读过,推荐这样的做法,但如果你有大量的指针,就会有大量的new调用,我想会是缓慢的一个职位。

+0

“是否值得通过使用指针而不是值来减少依赖关系(从而编译时间)?” - 我看不到如何使用指针“减少依赖关系” - 以及它与编译时间的关系。 – Dai

+0

没有任何关于需要“新”调用的指针。我可以编写一堆代码,并在各处指向指针,而不是一个'new'调用。 –

+0

@Dai:你可以转发声明pointee类型,而不是'#include'这个类型完全定义的整个头文件。 –

回答

2

如果您的程序不能保证动态分配,请不要为了项目组织而介绍它。那绝对会是一个虚假的经济。

你真正想要做的是试图完全减少类间依赖的数量。

但是,只要你的耦合是明智的,树状的,不要太担心。如果你正在使用预编译头文件(你是,对吧?),那么这对编译时间来说都不重要。

+0

我认为这个问题也是很大的依赖树。小的,可能不相关的某些标题变化可能会导致大部分项目重新编译。对于大型项目来说,这可能会令人望而却步,比如防止夜间搭建和测试。当我在汉堡申请Star Division(Star Office,后来的OpenOffice)工作时,这是一个问题:“如果你想添加一个虚拟函数到一个多态类而不重新编译所有使用这个类的文件;你在哪里放置类声明中的新函数?“ (最后,因为VTable中所有早期的偏移量都没有改变)。 –

+0

“你真正想做的是试图完全减少类间依赖的数量。”任何有关这方面的参考资料? – magnus

+0

@ user1420752:任何有关软件设计的好书,真的 –

3

这是大多数人称之为皮姆普成语(http://c2.com/cgi/wiki?PimplIdiom)。

简单的答案

我高度怀疑,你没有这个良好的使用情况,并应该避免不惜一切代价。

我的经验

主要方式,平普尔曾经对我有用的是使一个实现细节保密。它实现了这一点,因为你不需要包含你的依赖关系的头文件,但可以简单地转发声明它们的类型。

如果你想提供一个SDK的人,它使用引擎盖下的一些Boost库的代码,但是你想要的后来换是出于对其他一些库的选项,而不产生任何问题对于你的SDK的消费者来说,Pimpl可以有很大的意义。

它还有助于在实现上创建一个门面,以便您可以控制整个公开接口,而不是暴露您隐式依赖的库,从而控制您无法控制的整个接口并可能改变,可能暴露过多,可能难以使用等。

+0

我在这里看不到Pimpl的证据。 –