知识产权教育网站建设,iis 建网站手机访问,高端网吧电脑配置,WordPress为啥这么慢奇异递归模板模式(Curiously Recurring Template Pattern) - 知乎 (zhihu.com)
本文来自上面的文章#xff01;#xff01;#xff01;本菜鸡学习和记录一下。
CRTP是C模板编程时的一种惯用法#xff1a;把派生类作为基类的模板参数。
1.静态多态
#include iostrea…奇异递归模板模式(Curiously Recurring Template Pattern) - 知乎 (zhihu.com)
本文来自上面的文章本菜鸡学习和记录一下。
CRTP是C模板编程时的一种惯用法把派生类作为基类的模板参数。
1.静态多态
#include iostream
using namespace std;template typename Child
struct Base
{void interface(){static_castChild*(this)-implementation();}
};struct Derived : BaseDerived
{void implementation(){cerr Derived implementation\n;}
};struct test : Basetest
{void implementation(){cerr test\n;}
};int main()
{Derived d;d.interface(); // Prints Derived implementationtest t;t.interface();return 0;
}
基类为Base是模板类子类Drived继承自Base同时模板参数为Drived基类中有接口
interface而子类中有接口对应实现implementation基类interface中将this通过static_cast转换为模板参数类型这里是Drived并调用该类型的implemention方法。
为什么是static_cast而不是dynamic_cast?
因为只有继承了Base的类型才能调用interface且这里是向下转型所以采用static_cast是安全的。
不太理解
通过CRTP可以使得类具有类似于虚函数的效果同时没有虚函数调用时的开销虚函数调用时需要通过虚函数指针查找虚函数表进行调用同时类的对象的体积相比使用虚函数也会减少不需要存储虚函数指针但是缺点是无法动态绑定。
2.
templatetypename Child
class Animal
{
public:void Run(){static_castChild*(this)-Run();}
};class Dog :public AnimalDog
{
public:void Run(){cout Dog Run endl;}
};class Cat :public AnimalCat
{
public:void Run(){cout Cat Run endl;}
};templatetypename T
void Action(AnimalT animal)
{animal.Run();
}int main()
{Dog dog;Action(dog);Cat cat;Action(cat);return 0;
}
Dog继承自Animal且模板参数为DogCat继承自Animal且模板参数为Cat
Animal,Dog,Cat中都声明了RunAnimal中的Run是通过类型转换后调用模板类型的Run方法实现的。在Action模板参数中接收Animal类型的引用或指针并在其中调用了animal对象的Run方法由于这里传入的是不同的子类对象因此Action中的animal也会有不同的行为。
3.添加方法减少冗余
//Vec3
struct Vector3
{float x;float y;float z;Vector3() default;Vector3(float _x, float _y, float _z);inline Vector3 operator(const Vector3 rhs);inline Vector3 operator-(const Vector3 rhs);//....
};inline Vector3 operator(const Vector3 lhs, const Vector3 rhs);
inline Vector3 operator-(const Vector3 lhs, const Vector3 rhs);
//....//Vec2
struct Vector2
{float x;float y;Vector2() default;Vector2(float _x, float _y);inline Vector2 operator(const Vector2 rhs);inline Vector2 operator-(const Vector2 rhs);//....
};inline Vector2 operator(const Vector2 lhs, const Vector2 rhs);
inline Vector2 operator-(const Vector2 lhs, const Vector2 rhs);
//.... 类型Vector3需要实现,-,,-等运算符重载。 类型Vector2需要实现,-,,-等运算符重载。
其中-这两个运算符可以采取,-运算符实现这时候可以把,-给抽象出来减少代码冗余。
templatetypename T
struct VectorBase
{T underlying() { return static_castT(*this); }T const underlying() const { return static_castT const(*this); }inline T operator(const T rhs) { this-underlying() this-underlying() rhs;return this-underlying();}inline T operator-(const T rhs){this-underlying() this-underlying() - rhs;return this-underlying();}//.....
};struct Vector3 : public VectorBaseVector3
{float x;float y;float z;Vector3() default;Vector3(float _x, float _y, float _z){x _x;y _y;z _z;}
};inline Vector3 operator(const Vector3 lhs, const Vector3 rhs)
{Vector3 result;result.x lhs.x rhs.x;result.y lhs.y rhs.y;result.z lhs.z rhs.z;return result;
}inline Vector3 operator-(const Vector3 lhs, const Vector3 rhs)
{Vector3 result;result.x lhs.x - rhs.x;result.y lhs.y - rhs.y;result.z lhs.z - rhs.z;return result;
}
//......int main()
{Vector3 v0(6.0f, 5.0f, 4.0f);Vector3 v2(4.0f, 5.0f, 6.0f);v0 v2;v0 - v2;return 0;
}
在VectorBase中实现了,-
它们依赖子类的和-运算符的实现。