微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Code Complete关于封装的C ++建议?

如何解决Code Complete关于封装的C ++建议?

| 在“代码完成”中有关“良好封装”的部分中,建议隐藏私有实现详细信息。用C ++给出了一个例子。这个想法基本上是将接口与实现完全分开,即使在类级别也是如此。
class Employee {
public:
    ...
    Employee( ... );
    ...

    FullName GetName() const;
    String GetAddress() const;

private:
    EmployeeImplementation *m_implementation;
};
这真的是时间的好利用吗?这不仅效率低下(这会给性能带来什么样的损失?),而且代码完整性(“管理复杂性”)的座右铭似乎已经被颠倒了-这不会增加复杂性吗?     

解决方法

        PIMPL惯用语的另一个优势可能在于维护ABI。请参阅实践中的“ Pimpl成语”。 类的大小保持不变。这意味着您可以更改内部实现,同时保持接口完整。 如果实现以编译形式(lib,dll等)分发,则在某些情况下,您可能只需要替换库而不必重新编译使用该类的代码。因此,只要公共接口不变,就可以将代码解耦为一个完全独立的模块。 正如其他人所述,它还减少了编译时间,在某些情况下这可能是足够的理由。     ,        好吧,由于您的头文件现在仅包含公共成员和一个指向私有实现的指针,因此它确实增加了封装。 由于额外的间接级别,它还会(略微?)降低性能。 “减少编译时间”是这里的关键问题。 如果您(您的公司)是该类的唯一用户,那么我认为您没有任何理由使用此习语。您将获得较低的性能,并且无论如何都应该每天(或定期)重建源代码(应该知道类之间的依赖关系)。 这意味着,如果您是该类的唯一使用者,则编译时间在很大程度上无关紧要。 如果您要分发库,那么情况就完全不同了。标头的更改意味着即使您更改了类的私有部分,您拥有的任何客户端也都需要重建其应用程序才能使用新版本。在这里使用pimpl惯用语意味着更改对动态库的用户是不可见的。     ,        通过指针进行的间接间接访问会导致额外的高速缓存未命中,并降低程序速度。 AFAIK,最常建议使用此惯用法(PIMPL)以减少编译时间。假设您有一个
employee.h
头,其中包含类中的所有字段,而不仅仅是一个指针。现在,无论何时更改员工详细信息(例如,添加或删除字段),都必须重新编译每个文件,包括
employee.h
。如果您只有一个指向
employee.cpp
中定义的实现类的指针,则在更改
EmployeeImplementation
时仅需重新编译
employee.cpp
。 现在,减少的编译时间值得增加成本吗?只有您可以决定。     ,        我认为pimpl习惯用法的主要优点(或至少其中一项)不是节省编译时间,而是允许组件之间的松耦合,即打破依赖关系。 假设您提供了许多其他组件使用的基础结构库。然后,如@zvrba所示,每次更改私有实现详细信息时,所有客户端都必须重新编译。这可能没什么大不了的,但是在大型复杂项目中,组件之间的集成可能是一项复杂的任务。使用pimpl,如果您的库是动态的(dll,.so),则客户端不需要任何操作。     ,        这个习语用于对较差的标头进行抽象,仅此而已。仅在定义类所需的类型涉及包括泄漏宏的标头,需要很长时间才能编译的标头等情况下才使用它。除此之外,通常不认为这样做是正确的。由于您的实现无论如何都需要动态分配和引用语义,因此您也可以使其成为接口并提供在cpp文件中具有定义的
CreateForMyPlatform()
方法。至少您可以在这种情况下使用智能指针。     

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。