C++ 静态多态性的策略和CRTP之间有什么区别?
我希望有一个具有多个可能实现的接口,在编译时选择。我看到CRTP是实现此功能的首选习惯用法。为什么呢?另一种选择是策略模式,但我在任何地方都没有提到这种技术:C++ 静态多态性的策略和CRTP之间有什么区别?,c++,design-patterns,inheritance,crtp,static-polymorphism,C++,Design Patterns,Inheritance,Crtp,Static Polymorphism,我希望有一个具有多个可能实现的接口,在编译时选择。我看到CRTP是实现此功能的首选习惯用法。为什么呢?另一种选择是策略模式,但我在任何地方都没有提到这种技术: template <class Impl> class StrategyInterface { public: void Interface() { impl.Implementation(); } void BrokenInterface() { impl.BrokenImplementation(); }
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;
模板
类策略接口
{
公众:
void接口(){impl.impl.Implementation();}
void brokerninterface(){impl.brokernimplementation();}
私人:
Impl-Impl;
};
类策略实现
{
公众:
void实现(){}
};
模板
类crtp接口
{
公众:
void Interface(){static_cast(this)->Implementation();}
void brokerninterface(){static_cast(this)->brokernimplementation();}
};
类CrtpImplementation:公共CrtpInterface
{
公众:
void实现(){}
};
战略接口;
crtp实施crtp;
不幸的是,
brokerinterface
在这两种情况下都不会被编译器捕获,除非我真的尝试使用它。对我来说,策略变体似乎更好,因为它避免了难看的静态转换
,并且使用组合而不是继承。CRTP是否还允许其他策略不允许的情况?为什么主要使用CRTP?策略模式的通常实现与您的CRTP实现完全相同。基类定义了某种算法,给出了在派生类中实现的一些部分
因此,CRTP实施了该战略模式。您的StrategyInterface只是委托细节的实现,而不是策略模式的实现
虽然两个实现都达到了相同的效果,但我更喜欢CRTP,因为它可以利用可能的空基类优化。除了静态多态性之外,CRTP还提供了覆盖基类函数的能力,因为它使用了继承机制
template <class Impl>
class BaseInterface
{
void genericFunc() { some implementation; }
}
模板
类基类接口
{
void genericFunc(){some implementation;}
}
如果使用CRTP,派生类可以选择将genericFunc()覆盖为“特殊”实现,以防genericFunc()不适合。Strategy patten将无法提供正常继承带来的功能
策略模式的一个优点是,如果BasedInterface需要在Impl中使用依赖类型,这将比CRTP容易得多
template <class Impl>
class BaseInterface
{
using SomeDerivedType = typename Impl::SomeType;
}
模板
类基类接口
{
使用SomeDerivedType=typename Impl::SomeType;
}
实际上,战略示例直接出自GoF手册。我认为你是对的,尽管这两个示例实际上以不同的方式实现了策略模式。因此,如果我理解正确,唯一的区别是我的策略示例将产生更大的对象大小?是的,这是唯一的区别,我可以看到。不,OP没有错过CRTP实现中的继承。由于您似乎不理解CRTP,您可能不应该回答这个问题。@Yakk Than请您友好一点,修复维基百科中损坏的描述:。特别是派生的类:public Base
部分。谢谢。在C++11中,我可能会使用类似于((Impl*)this)->Implementation()
的C强制转换,因为它允许您将CRTP类用作私有基。您确定吗?我只是试了一下,但没用。这就是我的意思。根据CRTP库的使用情况,您可能需要也可能不需要将库中的函数公开。还可以使用reinterpret\u cast
。我通常尝试远离C风格的强制转换。在CRTP中,用self()
替换static_cast(this)
,并编写Impl*self(){return static_cast(this)}
和Impl const*self()const{return static_cast(this)}
。向self()
方法添加一些static\u assert
,并断言Impl
是一个子类。