C++ 通过内部指针隐藏实现细节

C++ 通过内部指针隐藏实现细节,c++,pimpl-idiom,C++,Pimpl Idiom,我有以下第三方类(只是一些指针的包装): 我想修改A的接口:禁用一些方法,添加一些新方法,同时隐藏其实现细节。我决定做以下工作: // new_a.h class AImpl; class A; class NewA { AImpl* pImpl; public: NewA( const A& a ); ... void newMethodOfA(); ... }; //new_a.cpp #include "a.h" NewA::New

我有以下第三方类(只是一些指针的包装):

我想修改
A
的接口:禁用一些方法,添加一些新方法,同时隐藏其实现细节。我决定做以下工作:

// new_a.h
class AImpl;
class A;

class NewA
{
    AImpl*   pImpl;

public:
    NewA( const A& a );
    ...
    void newMethodOfA();
    ...
};

//new_a.cpp
#include "a.h"
NewA::NewA( const A& a ): pImpl( a.getImpl() ) {}
...
void NewA::newMethodOfA()
{
    A( pImpl ).someMethodOfA();
}
...

这样做可以吗?也许有更好的解决办法?我想更改
接口,因为它不符合我的需要,也不想将其保存在我自己的代码中。

您在评论中这样说

我不想分配并持有*pImpl,因为它已经是某个指针(AImpl)的包装器

尽管有此要求,您还是在
NewA::newMethodOfA()
中分配了一个临时
a
对象。这比一次分配
A
并重新使用它要好多少?你的解决方案不好,因为1)你一次又一次地创建一个新的临时
a
,2)你强迫
NewA
的用户提供
a
的实例,而不是自己创建一个

我建议您咬紧牙关,只需制定一个适当的“PIMPL之上的PIMPL”实现(正如Obvlious船长所说):

这符合您的所有其他要求:

  • 您不想将
    a.h
    包含在
    new_a.h
  • 您希望提供一个经过修改的
    a
    界面,这样
    NewA
    的用户就不会了解
    a
    AImpl
  • 您想隐藏
    A的实现

  • 唯一不太符合的是,在代码中,您显示了
    A
    的默认构造函数将其
    pImpl
    成员初始化为0-这很奇怪!什么时候需要PIMPL类的用户提供PIMPL类包装的对象?请参阅维基百科。

    如果“A”具有虚拟成员函数,则此处很重要,在这种情况下,您可以从A派生并创建自己的成员函数集,如果需要,还可以从基类调用一些。@CyberGuy否,
    A
    没有虚拟函数。它不是为了多态而设计的。你想隐藏什么实现?。您的
    pImpl
    实际上是
    public
    。作为一个建议,您似乎想要像适配器模式所建议的那样:将pImpl放在pImpl之上?相反,我建议你只需微笑并使用siml
    A
    对象实际上是某个树的节点,因此会有很多这样的对象被创建。我不想在堆上分配它们,因为这会影响性能。所有真正的东西都在
    AImpl
    中。我认为为此目的在堆栈上创建临时对象比动态分配要快,但我可能错了。我发现这似乎是最好的解决方案,但在这种特殊情况下,只要
    A
    公开指向内部实现的指针,我想只使用它会更容易。。。
    // new_a.h
    class AImpl;
    class A;
    
    class NewA
    {
        AImpl*   pImpl;
    
    public:
        NewA( const A& a );
        ...
        void newMethodOfA();
        ...
    };
    
    //new_a.cpp
    #include "a.h"
    NewA::NewA( const A& a ): pImpl( a.getImpl() ) {}
    ...
    void NewA::newMethodOfA()
    {
        A( pImpl ).someMethodOfA();
    }
    ...
    
    // new_a.h
    class A;
    
    class NewA
    {
        A* pImpl;
    
    public:
        NewA();
        ~NewA();
    
        void newMethodOfA();
    };
    
    //new_a.cpp
    #include "a.h"
    NewA::NewA() : pImpl( new A() ) {}
    NewA::~NewA() { delete pImpl; }
    
    void NewA::newMethodOfA()
    {
        pImpl->someMethodOfA();
    }