c++ - STL 友好的 pImpl 类?

标签 c++ stl pimpl-idiom

我正在维护一个可能需要相当长的时间来构建的项目,因此我正在尝试尽可能减少依赖项。如果 pImpl 习语可以使用某些类,并且我想确保正确执行此操作,并且这些类可以与 STL(尤其是容器)很好地配合。下面是我的示例计划做什么 - 这看起来不错吗?我使用 std::auto_ptr 作为实现指针 - 这可以接受吗?使用 boost::shared_ptr 会是一个更好的主意吗?

以下是 SampleImpl 类的一些代码,该类使用名为 FooBar 的类:

// SampleImpl.h
#ifndef SAMPLEIMPL_H
#define SAMPLEIMPL_H

#include <memory>

// Forward references
class Foo;
class Bar;

class SampleImpl
{
public:
    // Default constructor
    SampleImpl();
    // Full constructor
    SampleImpl(const Foo& foo, const Bar& bar);
    // Copy constructor
    SampleImpl(const SampleImpl& SampleImpl);
    // Required for std::auto_ptr?
    ~SampleImpl();
    // Assignment operator
    SampleImpl& operator=(const SampleImpl& rhs);
    // Equality operator
    bool operator==(const SampleImpl& rhs) const;
    // Inequality operator
    bool operator!=(const SampleImpl& rhs) const;

    // Accessors
    Foo foo() const;
    Bar bar() const;

private:
    // Implementation forward reference
    struct Impl;
    // Implementation ptr
    std::auto_ptr<Impl> impl_;
};

#endif // SAMPLEIMPL_H

// SampleImpl.cpp
#include "SampleImpl.h"
#include "Foo.h"
#include "Bar.h"

// Implementation definition
struct SampleImpl::Impl
{
    Foo foo_;
    Bar bar_;

    // Default constructor
    Impl()
    {
    }

    // Full constructor
    Impl(const Foo& foo, const Bar& bar) :
        foo_(foo),
        bar_(bar)
    {
    }
};

SampleImpl::SampleImpl() :
    impl_(new Impl)
{
}

SampleImpl::SampleImpl(const Foo& foo, const Bar& bar) :
    impl_(new Impl(foo, bar))
{
}

SampleImpl::SampleImpl(const SampleImpl& sample) :
    impl_(new Impl(*sample.impl_))
{
}

SampleImpl& SampleImpl::operator=(const SampleImpl& rhs)
{
    if (this != &rhs)
    {
        *impl_ = *rhs.impl_;
    }
    return *this;
}

bool SampleImpl::operator==(const SampleImpl& rhs) const
{
    return  impl_->foo_ == rhs.impl_->foo_ &&
        impl_->bar_ == rhs.impl_->bar_;
}

bool SampleImpl::operator!=(const SampleImpl& rhs) const
{
    return !(*this == rhs);
}

SampleImpl::~SampleImpl()
{
}

Foo SampleImpl::foo() const
{
    return impl_->foo_;
}

Bar SampleImpl::bar() const
{
    return impl_->bar_;
}

最佳答案

如果 Foo 或 Bar 在复制时可能会抛出异常,则应考虑使用 copy-and-swap 进行赋值。如果没有看到这些类的定义,就不可能说它们是否可以。如果没有看到他们发布的界面,就不可能说他们将来是否会在你没有意识到的情况下改变这样做。

正如 jalf 所说,使用 auto_ptr 有点危险。它在复制或分配时的行为不符合您的要求。快速浏览一下,我认为您的代码不允许复制或分配 impl_ 成员,因此可能没问题。

如果您可以使用scoped_ptr,那么编译器将为您完成这项棘手的工作,检查它是否被错误地修改。 const 可能很诱人,但你无法交换。

关于c++ - STL 友好的 pImpl 类?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2028107/

相关文章:

c++ - 分离线程使用单例拥有的资源是否安全

php - 在 Qt C++ 中使用 openssl 解码和编码文本

C++ STL : a good way to parse a sensor response

c++ - 在 C++ 中检查空静态映射变量

c++ - 析构函数调用时访问冲突读取位置 0xfeeefe2

c++ - 针对 pimpl 的最终用户,pimpl 中的全局和私有(private)前向声明之间的区别

c++ - 如何从子类的构造函数初始化父类的私有(private)成员

c++ - 在 VS 2013 中使用初始化列表初始化 map 的 map

c++ - 用C++设置合并算法

c++ - pImpl 习语和可测试性