pimpl班的私人会员?

时间:2010-02-01 16:36:34

标签: c++ pimpl-idiom

在pimpl习惯用法中使用的实现类是否有任何理由可以拥有任何私有成员?我真正想到的唯一原因是保护自己免受自己的伤害 - 即私人成员用于在类和用户之间强制执行某种契约,在这种情况下,类和用户是密切相关的,所以它似乎没必要。

7 个答案:

答案 0 :(得分:11)

我认为人们将Pimpl 习语与Adapter / Bridge / Strategy 模式混淆。习语是一种语言特有的。模式可以应用于多种语言。

Pimpl成语是为了解决C ++中的以下问题而设计的:类的私有成员在类声明中是可见的,这会向类的用户添加不必要的#include依赖项。这个习语也称为编译器防火墙

如果实现是直接在外部类的相应* .cpp文件中编写的,并且在模块外部无法访问,那么我认为仅仅使用一个结构用于Pimpl类就完全没问题了。为了进一步强化实现不是要直接重用的想法,我将它们定义为私有内部结构:

// foo.h
class Foo : boost::noncopyable
{
public:
   ...

private:
   struct Impl;
   boost::scoped_ptr<Impl> impl_;
};

// foo.cpp
struct Foo::Impl
{
   // Impl method and member definitions
};

// Foo method definitions

只要有实现类的头文件,我想我们不再谈论Pimpl习语。我们宁愿谈论适配器,桥接,策略,接口类等......

只需2美分。

答案 1 :(得分:6)

取决于你的pImpl实现 - 特别是你强制执行类不变量的地方,但总的来说,我认为impl部分不需要有protected / private成员。实际上,我通常将其声明为结构。

答案 2 :(得分:4)

理论上,一个pimpl类仍然只是一个类似于其他类的类。它是接口的具体实现并不意味着其他代码本身不是pimpl类的客户端。

也就是说,实际上我发现pimpl类更倾向于使用某些成员函数而非完全成熟的对象更接近结构,并且不需要将接口与实现分开。

答案 3 :(得分:2)

为什么不应该有私人会员?仅仅因为您定义了一个接口,因为PIMPL并不意味着您将不会想要使用该类。

它还是一堂课。数据应该是私有的或受保护的。公共,私人或受保护的数据操作永远不可访问。您可能希望公开,保护或公开的操作。

答案 4 :(得分:1)

  

我能想到的唯一原因   是保护自己免受自己的伤害

这就是为什么“私人”和“受保护”首先出现的原因。当然你应该在你的实现中使用它们 - 唯一不希望的是如果实现没有行为(在这种情况下它不是真正的实现)。

答案 5 :(得分:0)

(我误解了这个问题,所以我改变了我的答案。)

类与pimpl一起指向的实现类应该是一个常规类,其中包含隐藏私有详细信息的原因。事实上,它通常是一个预先存在的类,后来添加了pimpl层来破坏依赖关系,并且可能会简化界面。

答案 6 :(得分:0)

因为private意味着更好的数据封装。

我知道,这似乎很愚蠢,但我们有一种在工作中定义界面非常简单的方法:

class Interface;

class Concrete { public: .... private: Interface* m_interface; }

class ConcreteFoo: public Interface {};

主要优势:您可以随时换取另一个ConcreteBar。事实上,它是PimplStrategy模式的组合,Concrete的构造函数将调用Factory来负责为有效对象提供服务。< / p>

如果您无法想到实现心脏的第二种方式,只需将其封装在一个类中即可。这样,如果你以后必须重构,你只需要用完全相同的方法组合一个抽象的Interface,改变一些指针(和构造函数),你就没事了;)< / p>