【发布时间】:2010-01-08 14:16:39
【问题描述】:
我正在维护一个可能需要相当长的时间来构建的项目,因此我试图尽可能减少依赖关系。如果pImpl 成语和我想确保我正确执行此操作并且这些类将与 STL(尤其是容器)很好地配合使用,则某些类可以使用。这是我计划做的一个示例 - 确实这个样子好吗?我使用std::auto_ptr 作为实现指针——这可以接受吗?使用boost::shared_ptr 会更好吗?
下面是 SampleImpl 类的一些代码,该类使用名为 Foo 和 Bar 的类:
// 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_;
}
【问题讨论】:
-
boost::scoped_ptr几乎就是为此目的而创建的。它比auto_ptr更合适,因为它根本不允许更改所有权。 -
@Rob 你的评论很好,我觉得我不得不删除我的答案;)
-
@Andreas,你最初是对的,我正在评论 Rob 的评论。如果
Foo的构造函数在new Foo()的构造过程中抛出异常,删除对象不是你的责任,由语言保证内存会被释放。 -
@Idan K 不,实际上我错了;)
SampleImpl的内存将被删除,但SampleImpl的构造函数分配的内存不会被删除,除非可以找到内存的释放函数(即类似于auto_ptr的析构函数)。有关详细信息,请参阅标准 5.3.4/17。
标签: c++ stl pimpl-idiom