zoukankan      html  css  js  c++  java
  • 奇异递归模版模式不“奇异”

      同学们是否有听说过奇异递归模版模式(CRTP)?听说过的同学大致也知道其代码编写格式是怎么样的?但是,同学们是否有弄清楚过其是怎么达到这种效果的?接下来就简单聊聊!

    一、奇异递归模板模式

      下面是奇异递归模板模式的一般编写格式:

     1 template<typename T>
     2 class Base
     3 {
     4 public:
     5     Base()
     6     {
     7         std::cout << "Base::Base<" << typeid(T).name() << "> ctor
    ";
     8     }
     9     ~Base()
    10     {
    11         std::cout << "~Base::Base<" << typeid(T).name() << "> dtor
    ";
    12     }
    13     void Interface()
    14     {
    15         std::cout << "Base::Interface()
    ";
    16         static_cast<T*>(this)->Implement1();
    17     }
    18 };
    19 
    20 
    21 class D : public Base<D>
    22 {
    23 public:
    24     D()
    25     {
    26         std::cout << "D::D<" << typeid(this).name() << "> ctor
    ";
    27     }
    28     ~D()
    29     {
    30         std::cout << "~D::D<" << typeid(this).name() << "> dtor
    ";
    31     }
    32 
    33     void Implement()
    34     {
    35         std::cout << "D::Implement()
    ";
    36     }
    37 };

      有一个基类模板,子类继承该基类时,使用子类实例化基类。起到调用基类接口实际上动态调用子类方法的作用,又被称之为“静态多态”(和重载不同)。调用方法如下:

    1 int main()
    2 {
    3     D b;
    4     b.Interface();
    5     return 0;
    6 }

      运行结果:

         

      要想弄清楚奇异递归模板模式如何达到这种效果,得先弄清楚两个基础问题:

    1. 类模板或函数模板什么时候被编译?
    2. std::static_cast能否向上转换?

    二、类模板或函数模板什么时候被编译?

      回答类模板或函数模板什么时候被编译前,先问自己:函数模板和模板函数,类模板和模板类的区别是什么。思考下... ...。其实类模板或函数模板,就是带有模板类型参数的类或函数,比如上面的奇异递归模板就是一个类模板;模板类或函数,就是实例化模板的类或函数,比如子类继承基类就是模板类,也叫做模板实例化。我们编写的类模板或函数模板,在没有实例化前,是不会被编译器编译。怎么验证呢?很简单,没有实例化上面的奇异递归模板时,我随便写过不存在的调用函数,编译不会出现错误。如下类模板:

     1 template<typename T>
     2 class Base
     3 {
     4 public:
     5     Base()
     6     {
     7         std::cout << "Base::Base<" << typeid(T).name() << "> ctor
    ";
     8     }
     9     ~Base()
    10     {
    11         std::cout << "~Base::Base<" << typeid(T).name() << "> dtor
    ";
    12     }
    13     void Interface()
    14     {
    15         std::cout << "Base::Interface()
    ";
    16         static_cast<T*>(this)->Implement1(); // 不存在的函数
    17         auto value = T::value;               // 不存在的值
    18     }
    19 };

      

      如果实例化类模板,那么就会编译报错:

          

      预处理后的预处理文件还是没有对类模板进行类型推导:

      

      所以,通过上面的验证,类模板或函数模板必须要实例化,然后编译器才会在编译阶段的时候进行类型推导并编译出obj文件。

    三、std::static_cast能否向上转换?

      先按照老规则,官方文档链接:static_cast conversion - cppreference.com

      第9种情况说明了std::static_cast可以向上转换,但也强调,这种转换并不进行检查以确保转换后对象的成员是否存在。下面可以通过代码验证:

     1 class B {
     2 public:
     3     B()
     4         : _b(1)
     5     {
     6         std::cout << "B::B() ctor
    ";
     7     }
     8     virtual ~B()
     9     {
    10         std::cout << "B::~B() dctor
    ";
    11     }
    12 
    13 private:
    14     int _b;
    15 };
    16 
    17 class D : public B
    18 {
    19 public:
    20     D()
    21         : _d(2)
    22     {
    23         std::cout << "D::D() ctor
    ";
    24     }
    25     ~D()
    26     {
    27         std::cout << "D::~D() ctor
    ";
    28     }
    29     void Func()
    30     {
    31         //this->_d = 2;
    32         std::cout << "D::Func() " << _d << std::endl;
    33     }
    34 private:
    35     int _d;
    36 };
    37 
    38 int main()
    39 {
    40     auto b = new B();
    41     auto d = static_cast<D*>(b);
    42     d->Func();
    43     return 0;
    44 }

      

          

      虽然转换后的子类可以正常调用子类函数,但是子类成员变量是随机值,这个也验证了官方文档中第9条转换规则中强调的问题。关于奇异递归模板模式的作用和使用问题,在实际项目中没有使用过,但是在boost等一些开源库中有涉及到它,感兴趣的同学可以访问下面的参考链接地址,进一步了解和学习奇异递归模板模式。

    参考:The Curiously Recurring Template Pattern (CRTP) - Fluent C++ (fluentcpp.com)

  • 相关阅读:
    实现可重启线程
    让别人能登陆你的mysql
    zmq消息订阅
    git备忘
    【LeetCode】数组排列问题(permutations)(附加next_permutation解析)
    【LeetCode】 数相加组合 Combination Sum
    【LeetCode】【找元素】Find First and Last Position of Element in Sorted Array
    【LeetCode】【数组归并】Merge k Sorted Lists
    【LeetCode】【动态规划】Generate Parentheses(括号匹配问题)
    【Leetcode】Remove Nth Node From End of List
  • 原文地址:https://www.cnblogs.com/smartNeo/p/14783408.html
Copyright © 2011-2022 走看看