C++ 静态多态性的策略和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(); }

我希望有一个具有多个可能实现的接口,在编译时选择。我看到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;
模板
类策略接口
{
公众:
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
是一个子类。