CRTP 模式通常用于启用静态多态性和混合(参数化)行为的能力。为了说明两种选择,首先定义一个通用模板很方便
template
<
typename Derived
>
class enable_down_cast
{
private:
// typedefs
typedef enable_down_cast Base;
public:
Derived const* self() const
{
// casting "down" the inheritance hierarchy
return static_cast<Derived const*>(this);
}
// write the non-const version in terms of the const version
// Effective C++ 3rd ed., Item 3 (p. 24-25)
Derived* self()
{
return const_cast<Derived*>(static_cast<Base const*>(this)->self());
}
protected:
// disable deletion of Derived* through Base*
// enable deletion of Base* through Derived*
~enable_down_cast() = default; // C++11 only, use ~enable_down_cast() {} in C++98
};
然后为你想要的行为类型定义一个接口类模板
template<typename FX>
class FooInterface
:
// enable static polymorphism
public enable_down_cast< FX >
{
private:
// dependent name now in scope
using enable_down_cast< FX >::self;
public:
// interface
void foo() { self()->do_foo(); }
protected:
// disable deletion of Derived* through Base*
// enable deletion of Base* through Derived*
~IFooInterface() = default; // C++11 only, use ~IFooInterface() {} in C++98/03
};
要获得此接口的不同实现,只需将每个派生自FooInterface
其自身的不同类定义为奇怪的重复模板参数:
class FooImpl
:
public FooInterface< FooImpl >
{
private:
// implementation
friend class FooInterface< FooImpl > ;
void do_foo() { std::cout << "Foo\n"; }
};
class AnotherFooImpl
:
public FooInterface< AnotherFooImpl >
{
private:
// implementation
friend class FooInterface< AnotherFooImpl >;
void do_foo() { std::cout << "AnotherFoo\n"; }
};
另一种方法是参数化接口的不同实现。这一次,类模板同时依赖于一个模板模板参数和一个非类型参数
template<template<int> class F, int X>
class BarInterface
:
public enable_down_cast< F<X> >
{
private:
// dependent name now in scope
using enable_down_cast< F<X> >::self;
public:
// interface
void bar() { self()->do_bar(); }
protected:
// disable deletion of Derived* through Base*
// enable deletion of Base* through Derived*
~BarInterface() = default; // C++11 only, use ~BarInterface() {} in C++98/03
};
然后实现是另一个类模板,它从接口派生,其自身和非类型参数作为参数
template< int X >
class BarImpl
:
public BarInterface< BarImpl, X >
{
private:
// implementation
friend class BarInterface< ::BarImpl, X >;
void do_bar() { std::cout << X << "\n"; }
};
这就是您对它们的称呼:
int main()
{
FooImpl f1;
AnotherFooImpl f2;
BarImpl< 1 > b1;
BarImpl< 2 > b2;
f1.foo();
f2.foo();
b1.bar();
b2.bar();
return 0;
}
您问题中的课程不太适合这种一般模式。如果您可能想提供Derived
一些类似 CRTP 的行为,那么您可以这样做
class Derived1
:
public CRTP< Derived1 >
{
};
template<int I>
class Derived2
:
public CRTPInt< Derived2, I >
{
};
更新:基于来自https://stackoverflow.com/a/11571808/819272的讨论,我发现原始答案仅在 Visual Studio 2010 上编译,但由于某些 Microsoft 特定的非便携式功能而未在 gcc 上编译。例如,self()
函数 fromenable_down_cast
是其派生类中的(模板)依赖名称,因此如果没有显式using
指令则不可见。此外,我添加了具有正确保护级别的默认析构函数。最后,我将我的原始类重命名为enable_crtp
,enable_down_cast
因为这正是它所做的:手动启用静态多态性,编译器自动启用动态多态性。