少于 1 分钟阅读

关于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。

分类:

更新时间: