1

我有两个类AB其中B使用类的对象A,像这样

class A {
    private:
        int foo_;

    A(const int &foo): foo_(foo) {}
}

class B {

    // STUFF

    inline C operator()(A a)
}

目前,我已将两者的定义放在一个.h文件中,并且代码可以正确编译和执行。

我的问题是:我可以屏蔽多少 class 的实现A,例如通过将代码行移动.cpp到要单独编译和链接的文件?我可以屏蔽private成员和方法的实现(外部用户不直接访问的所有内容)吗?如何?我应该使用哪些 C++ 关键字?

非常感谢您提前。

4

3 回答 3

4

屏蔽实现可以通过PIMPL 习惯用法或使用简单的多态性来完成,这是一种工厂方法模式。基本上,你创建一个接口类,IA像这样说:

/* File: A.h */
#include <memory> /* For std::shared_ptr */
class IA;
/* Change the line below to boost::shared_ptr<> or
 * another implementation of a shared-pointer.
 * Read more:
 * http://en.wikipedia.org/wiki/Smart_pointer#shared_ptr_and_weak_ptr
 */
typedef std::shared_ptr<IA> APtr;

class IA {
public:
    static APtr Create(const int foo);
    IA(){}
    virtual ~IA(){}
    virtual void somePublicMethod() = 0;
};

在您的 A.cpp 中,您将拥有它的实现:

/* File: A.cpp */
#include "A.h"

class A : public IA
{
public:
    A(const int foo):foo_(foo){}
    void somePublicMethod(){/* Your awesome implementation goes here */}
};

APtr IA::Create(const int foo)
{
    return APtr(new A(foo));
}

这样,您只传递接口并且只向外部世界公开公共方法,内部方法位于您的 CPP 文件中。

好处:

  • 对用户完全隐藏实现

缺点:

  • 您需要为要隐藏的每个类创建一个接口
  • 您的用户必须调用工厂方法来创建实例。例如Create()在上面的例子中。
  • 您将始终让您的类实例在堆内存中而不是在堆栈中,即,您的实现实例将始终必须是一个指针。(阅读更多:堆内存与栈内存
于 2013-06-11T08:08:18.963 回答
2

关于 pImpl 成语可以隐藏什么:

  • 您可以将所有函数定义(其实现,包括构造函数及其初始化列表)移动到Impl类中
  • 然后,您可以将私有类型、数据成员函数放入 Impl 类中,除非它们会影响类行为(例如,私有构造函数、析构函数和运算符对类的用户有影响)
  • 您可以将类静态数据成员的定义和初始化移动到实现文件中
  • 根据 Arne 的评论,私有基类通常可以移动到实现中(除非您在公共或受保护的数据成员中使用它们的 typedef 等,根据他的评论,这很难看!)
于 2013-06-11T08:14:39.543 回答
2

如果你不需要C operator()(A a)inline你可以转发声明参数A如下

class A;

然后,您可以将其定义移动到另一个标题并将其包含在使用它的位置。

这里有更多关于前向声明的细节。

于 2013-06-11T08:22:09.960 回答