在C ++中,通常会看到以下内容:
C类标题
//== C.h ==//
#pragma once
#include "B.h"
class C
{
B b;
};
B类标题
//== B.h ==//
#pragma once
#include "A.h"
class B
{
A a;
};
A类标题
//== A.h ==//
#pragma once
class A
{
};
因为C.h
包含B.h
,B.h
包含A.h
; C.h
最终了解有关A.h
的实施细节。在这种情况下,标题只包含三个级别,但在包含一个标题的大型项目中,很快就会包含数百个额外的标题。也导致编译时间过长。
在C ++ 11中,我可以将标题声明如下:
C类标题:
//== C.h ==//
#pragma once
#include <memory>
// proto
class B;
class C
{
std::unique_ptr<B> b;
};
B类标题
//== B.h ==//
#pragma once
#include <memory>
// proto
class A;
class B
{
std::unique_ptr<A> a;
};
A类标题
//== A.h ==//
#pragma once
class A
{
};
当用智能指针替换所有成员(类,结构)时,我可以包含C.h
,而不必知道类B的实现。每个cpp文件现在只需知道它的成员,而不必知道关于它成员的记忆布局。
我的问题是:
答案 0 :(得分:4)
如果直接数据成员的类型支持复制,则直接数据成员默认支持复制。它的效率最高。如果有人觉得用更短的构建时间进行交易是值得的,那么为什么不使用C ++,为什么不使用C ++,那么只使用最大限度地利用这种权衡的语言,例如Java或C#。
换句话说,它似乎是一个不合时宜的想法。
为了在使用C ++的同时缩短构建时间,请考虑更快的机器或构建服务器停放。
答案 1 :(得分:1)
用指针替换所有成员并不是一个好主意,因为它会添加额外的解除引用层。直接成员实际上是在包含对象中分配的,因此访问它只需要与包含对象位置的固定偏移量。
如果隐藏指针后面的所有内容,则需要访问指针成员,然后取消引用指针以访问数据(这将在内存中的其他位置)。这在个人的基础上是一个微不足道的开销,但如果原则在整个计划中得到扩展,它很快就会加起来。
要记住的另一个问题是可维护性。如果您通过指针存储所有内容,则需要手动包含适当的构造和复制。这可能会导致大型项目出现各种问题,因为这会增加程序员错误的可能性。相比之下,如果您使用直接成员,编译器会自动执行大量操作。
值得查看的替代方案是PIMPL设计模式(私有实现或指向实现)。它本质上是一种将类的私有细节隐藏在其源文件中的方法,以减少标头依赖性。