【发布时间】:2014-01-11 13:57:38
【问题描述】:
我希望有一个在编译时选择的具有多种可能实现的接口。我看到 CRTP 是实现这一点的首选习语。这是为什么?另一种方法是策略模式,但我没有看到任何地方提到过这种技术:
template <class Impl>
class StrategyInterface
{
public:
void Interface() { impl.Implementation(); }
void BrokenInterface() { impl.BrokenImplementation(); }
private:
Impl impl;
};
class StrategyImplementation
{
public:
void Implementation() {}
};
template <class Impl>
class CrtpInterface
{
public:
void Interface() { static_cast<Impl*>(this)->Implementation(); }
void BrokenInterface() { static_cast<Impl*>(this)->BrokenImplementation(); }
};
class CrtpImplementation : public CrtpInterface<CrtpImplementation>
{
public:
void Implementation() {}
};
StrategyInterface<StrategyImplementation> str;
CrtpImplementation crtp;
BrokenInterface 在这两种情况下都不会被编译器捕获,不幸的是,除非我真的尝试使用它。 Strategy 变体对我来说似乎更好,因为它避免了丑陋的static_cast,并且它使用组合而不是继承。还有什么 CRTP 允许的,策略不允许的吗?为什么主要使用 CRTP?
【问题讨论】:
-
在 C++11 中,我可能会使用像
((Impl*)this)->Implementation()这样的 C 类型转换,因为它允许您使用 CRTP 类作为私有基础。 -
你确定吗?我刚试了一下,还是不行。
-
This 是我的意思。根据 CRTP 基础的用例,您可能需要也可能不需要在基础中公开功能。
-
它 works 和
reinterpret_cast也是如此。我通常尽量远离 C 风格的演员表。 -
在 CRTP 中将
static_cast<Impl*>(this)替换为self(),并写入Impl* self() { return static_cast<Impl*>(this); }和Impl const* self() const { return static_cast<Impl*>(this); }。在self()方法中添加一些static_assert以断言Impl是一个子类。
标签: c++ design-patterns inheritance crtp static-polymorphism