我正在为pimpl成语创建一个实用工具类,但是我有一些问题希望得到一些帮助:
这就是我所得到的:[sehe: 另见rev.1:https://gist.github.com/1379569/9f6cca5703e6195da65e34103393d901dde3b1bf ]
pimpl.h
template<typename T>
class pimpl
{
template <typename> friend class pimpl;
pimpl(const pimpl& other);
pimpl(pimpl&& other);
pimpl& operator=(const pimpl& other);
pimpl& operator=(pimpl&& other);
protected:
~pimpl();
struct implementation;
std::unique_ptr<implementation> impl_;
public:
pimpl();
template<typename P0>
pimpl(P0&& p0);
pimpl(const T& other);
pimpl(T&& other);
void swap(T& other);
};
pimpl_impl.h
// #include "pimpl.h" // TODO add header guards...
template<typename T>
pimpl<T>::pimpl() : impl_(new implementation()){}
template<typename T>
template<typename P0>
pimpl<T>::pimpl(P0&& p0) : impl_(new implementation(std::forward<P0>(p0))){}
template<typename T>
pimpl<T>::~pimpl(){}
template<typename T>
pimpl<T>::pimpl(const T& other) : impl_(new implementation(*((pimpl&)other).impl_)){}
template<typename T>
pimpl<T>::pimpl(T&& other) : impl_(std::move(((pimpl&)other).impl_)){}
template<typename T>
void pimpl<T>::swap(T& other)
{
impl_.swap(other.impl_);
}
这就是你如何使用它:
A.h
#include "pimpl.h"
class A : public pimpl<A>
{
A();
A(const A& other);
A(A&& other);
virtual ~A();
void foo();
};
A.cpp
#include "A.h"
#include "pimpl_impl.h"
template<>
struct pimpl<A>::implementation
{
void foo()
{
}
};
A::A() : pimpl(){}
A::A(const A& other) : pimpl(other){}
A::A(A&& other) : pimpl(std::move(other)){}
A::~A(){}
void A::foo(){impl_->foo();}
这很有效,但是当你将继承放入图片时它会很快崩溃:
class B : public pimpl<B>, public A
{
...
};
B::B() : pimpl() {} // pimpl ambiguous
pimpl
变得含糊不清......
关于如何避免这种想法?
答案 0 :(得分:4)
虽然我不建议因为Liskov而将pimpl填充到curious base class,但我认为没有任何真正的问题可以使它工作;
像@Nim建议的那样:在做
时,这一切似乎都很好class B : public pimpl<B>, public A
{
B() : pimpl<B>() {}
};
更新了Gist,其中包含适用于B的完整示例代码:
B.h
#include "A.h"
class B : public pimpl<B>, public A
{
public:
B();
B(const B& other);
B(B&& other);
virtual ~B();
void bar();
};
B.cpp
#include "pimpl_impl.h"
#include "B.h"
template<>
struct pimpl<B>::implementation
{
void bar()
{
}
};
B::B() : pimpl<B>(){}
B::B(const B& other) : pimpl<B>(other){}
B::B(B&& other) : pimpl<B>(std::move(other)){}
B::~B(){}
void B::bar(){ pimpl<B>::impl_->bar();}
main.cpp中:
#include "B.h"
int main()
{
A a;
B b;
}