我到处读到关于 CRTP 的信息,实际上在我编写的代码中,CTRP 类层次结构如下所示:
template< class T >
class Base
{
public:
int foo_interface()
{
return static_cast< T* >(this)->foo_implementation();
}
};
class Derived : public Base< Derived >
{
friend class Base< Derived >;
int foo_implementation()
{
return 5;
}
};
即接口和实现方法的名称不同。现在,我通常不希望实现方法从外部可见,这需要上面的朋友声明,并且在多级层次结构中被证明是一个主要的组合(即使使用此处描述的技巧)。
现在,我想出了以下内容:
// Base class
template< class T >
class A
{
public:
int foo()
{
std::cout << "I'm in A's foo!\n";
return static_cast< T * >(this)->foo();
}
};
// Deriving class
class B : public A< B >
{
public:
int foo()
{
std::cout << "I'm in B's foo!\n";
return 5;
}
};
// Deriving class with a nasty surprise...
class C: public A< C >
{
public:
// ...crap, no foo to be found!
int bar()
{
std::cout << "I'm in C's bar!\n";
return 12;
}
};
template< class T >
int call_foo(A< T > & t)
{
return t.foo();
}
B b;
C c;
现在,call_foo(b)
就像我期望的那样工作,调用 B 的 foo() 实现。同样地,call_foo(c)
也可以按预期工作(因为它不会……由于显而易见的原因,它会陷入无限循环)。我可以看到的一个缺点是,如果我忘记在派生类中实现一个方法(或拼写错误,忘记将其限定为 const,无论如何......),我会得到一个无限循环,所以它可能会产生那种错误有点难找到,因为它们没有在编译时被捕获。不过除此之外,它几乎就像普通的虚函数一样简单,而且我不必为隐藏实现方法而战。它看起来简单而优雅,但似乎没有人使用它......我的问题是,那么,有什么问题?为什么不是 没有使用这种方法吗?隐藏实现方法不是什么大不了的事吗?或者,当我在实际项目中尝试这种方法时,是否有某种不可估量的邪恶邪恶力量潜伏在那里,准备吞噬我的灵魂?