CRTP - 奇特重现模板模式
关于CRTP的cppreference资料,请看这里。
奇特重现模板模式是一种设计技术,而非设计模式。我们讲的 “设计技术”指的是在C++中,利用语言特性实现的设计技巧,而“设计模式”一词则相对狭义,指的是在任何(大多数)面向对象语言中都可以实现的设计思想。请做区分。
奇特重现模板模式是C++的一种惯用手法,可以实现伪“编译期多态”。举例(C++23 deducing this出现之前):
template <typename DerivedType>
class Base
{
public:
void someAction(void)
{
(static_cast<DerivedType *>(this))->implementation();
}
};
class DerivedA : public Base<DerivedA>
{
public:
void implementation(void)
{
std::cout << "DerivedA's implementation" << std::endl;
}
};
class DerivedB : public Base<DerivedB>
{
public:
void implementation(void)
{
std::cout << "DerivedB's implementation" << std::endl;
}
};
倘若我这么调用:
int main(void)
{
DerivedA object_x {};
DerivedB object_y {};
object_x.someAction();
object_y.someAction();
}
此时调用的someAction()
针对不同的Derived
类型,将发生不同的行为:
$ clang++ -v
clang version 10.0.0-4ubuntu1
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /usr/bin
Found candidate GCC installation: /usr/bin/../lib/gcc/x86_64-linux-gnu/9
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/9
Selected GCC installation: /usr/bin/../lib/gcc/x86_64-linux-gnu/9
Candidate multilib: .;@m64
Selected multilib: .;@m64
$ clang++ crtp.cpp -o crtp
$ ./crtp
DerivedA's implementation
DerivedB's implementation
第一行输出时,调用了Base<DerivedA>::someAction()
方法,将this
指针(此时为Base *
)静态转换成为DerivedA *
(因为DerivedType
参数被替换成为DerivedA
),调用其implementation()
方法,第二行输出同理。
很明显,这种静态转换可以在编译期实现伪“多态”,固然有其局限性(这是显然的),但是在一些场合中可以有很大的作用。比如,实现“混入类”(Mixin),这种模式可以避免多继承,在框架有意识地避免多继承时很有用。
之后会专注讲一些设计技术,欢迎订阅feed。