奇异递归模板设计模式-CRTP

首先写一个最简单的奇异递归
第一个例子

//奇异递归需要用到c++的模板特性
#include<iostream>
using namespace std;

//基类
template <typename Type>
class Animal
{
public:
	static int Counter;
	Animal()
	{
		++Counter;
	}
	~Animal()
	{
		--Counter;
	}
};
//因为是static所以需要在类外进行初始化
template <typename Type>int Animal<Type>::Counter = 0;


//派生类

class Dog :public Animal<Dog>//模板参给dog
{
public:
	//构造,析构给个默认
	Dog() = default;
	~Dog() = default;
};
class Cat :public Animal<Cat>//模板参给dog
{
public:
	//构造,析构给个默认
	Cat() = default;
	~Cat() = default;
};

int main()
{
	Dog d1, d2, d3;
	cout << Dog::Counter<<endl;
	Cat c1;
	cout << Cat::Counter << endl;

		return 0;
}





//这样就形成了一个奇异递归
//static int 本来是所有类共享,却打印出了不同值,违背了这个共享原则

//这是因为它是模板,它的模板参数不同(一个是cat,一个是dog),所以这是两个不同的类,
//所以个这个两个不是同一个Counter

第二个例子

//奇异递归需要用到c++的模板特性
#include<iostream>
using namespace std;
//第二个示例,用模板的方法实现一个多态
//基类
template <typename Type>
class Animal
{
public:
	void speak()
	{	//强转一下,将this转为Type*,调用他的speak
		static_cast<Type*> (this)->speak();
	}
	
};


//派生类

class Dog :public Animal<Dog>//模板参给dog
{
public:
	//构造,析构给个默认
	Dog() = default;
	~Dog() = default;
	void speak()
	{	
		cout << "汪汪"<<endl;
	}
};
class Cat :public Animal<Cat>//模板参给dog
{
public:
	//构造,析构给个默认
	Cat() = default;
	~Cat() = default;
	void speak()
	{
		cout << "喵喵" << endl;
	}
};

//模板调用函数
template <typename Type>
void test(Animal<Type>& t)
{
	t.speak();
}


int main()
{
	Dog d1;
	//实例化一个dog,调用test方法
	test(d1);


	Cat c1;
	test(c1);
	

		return 0;
}





//这样就形成了一个奇异递归
//static int 本来是所有类共享,却打印出了不同值,违背了这个共享原则

//这是因为它是模板,它的模板参数不同(一个是cat,一个是dog),所以这是两个不同的类,
//所以个这个两个不是同一个Counter

这个等价下面不使用模板来实现多态

//奇异递归需要用到c++的模板特性
#include<iostream>
using namespace std;
//第二个示例,用模板的方法实现一个多态
//基类

class Animal
{
public:
	virtual void speak() = 0;//给个纯虚函数,让子类去重写它
	
	
};


//派生类

class Dog :public Animal
{
public:
	//构造,析构给个默认
	Dog() = default;
	~Dog() = default;
	void speak()
	{	
		cout << "汪汪"<<endl;
	}
};
class Cat :public Animal
{
public:
	//构造,析构给个默认
	Cat() = default;
	~Cat() = default;
	void speak()
	{
		cout << "喵喵" << endl;
	}
};

模板调用函数
//template <typename Type>
//void test(Animal<Type>& t)
//{
//	t.speak();
//}

//等价于用多态来实现
void test(Animal&
<think>好的,我现在需要帮助用户理解奇异递归模板模式(CRTP)的定义、实现和示例。用户已经提供了三个引用资料,我需要结合这些内容来组织回答。 首先,CRTP的定义。根据引用[1]和[2],CRTP是一种C++设计模式,基类模板将派生类作为模板参数。基类通过模板参数访问派生类的成员,实现静态多态。需要明确说明基类和派生类的关系,特别是自引用的特点。 接下来是实现部分。引用[3]中的代码示例展示了基类模板如何接受派生类作为参数,并在基类中使用static_cast将this转换为派生类指针。这样基类可以调用派生类的方法,或者派生类重写基类的函数。需要分步骤说明基类模板的定义、派生类的继承方式,以及如何通过static_cast实现类型转换。同时,引用[1]提到的链式调用可能也是实现的一个方面,可以结合说明。 然后是示例部分。需要提供一个简单的代码示例,展示CRTP的具体应用。比如基类有某个方法,派生类实现后,基类通过模板参数调用派生类的方法。比如计数器模式,基类记录对象数量,派生类继承并自动更新计数。或者像引用[3]中的print函数,派生类重写基类的print方法,基类调用时显示不同信息。 另外,需要注意用户提到的行内公式和独立公式的格式要求。不过目前看来,CRTP的内容可能不涉及数学公式,但如果有涉及的地方需要正确使用LaTeX格式。 用户还要求生成相关问题,我需要考虑CRTP的常见应用场景、优缺点、与其他模式的区别,以及实际项目中的使用案例等。 现在检查引用内容是否准确。引用[1]提到基类返回派生类引用,引用[2]说明基类模板接受派生类作为参数,引用[3]给出了具体的代码结构。需要确保这些内容在回答中被正确引用,并在适当的位置添加引用标识。 可能需要注意术语的一致性,比如CRTP的不同称呼,确保使用用户提供的资料中的术语。同时,解释CRTP如何实现静态多态,与动态多态的区别,以及其优势(如性能提升,编译时多态)。 最后,结构要清晰,分点回答定义、实现、示例,每个部分简明扼要,代码示例正确,并符合用户的格式要求。</think>### 奇异递归模板模式(CRTP)解析 #### 1. **定义** 奇异递归模板模式(Curiously Recurring Template Pattern, CRTP)是C++中一种**静态多态**设计模式,其核心思想是**基类模板以派生类作为模板参数**,从而实现基类对派生类成员的直接访问[^2]。 这种模式通过模板的自引用特性(基类依赖派生类的类型)实现编译时的多态行为,避免运行时虚函数开销[^3]。 --- #### 2. **实现** CRTP的实现分为以下关键步骤: 1. **基类模板定义**:基类模板接受一个类型参数`Derived`(实际为派生类)。 2. **派生类继承**:派生类通过`public Base<Derived>`递归继承基类模板。 3. **类型转换**:基类通过`static_cast<Derived*>(this)`将自身指针转换为派生类指针,调用派生类方法。 **代码示例(基础结构)**: ```cpp template <typename Derived> class Base { public: void interface() { static_cast<Derived*>(this)->implementation(); // 调用派生类方法 } }; class Derived : public Base<Derived> { public: void implementation() { /* 具体实现 */ } }; ``` --- #### 3. **示例:对象计数器** 以下示例通过CRTP统计某个类的实例数量: ```cpp template <typename T> class Counter { public: static int count; Counter() { ++count; } ~Counter() { --count; } static int getCount() { return count; } }; template <typename T> int Counter<T>::count = 0; // 派生类继承基类模板并将自身作为参数传递 class MyClass : public Counter<MyClass> { /* 类定义 */ }; // 使用 MyClass obj1, obj2; std::cout << MyClass::getCount(); // 输出2 ``` 此例中,`Counter`基类通过模板参数`T`区分不同派生类的计数器,实现编译时类型隔离。 --- #### 4. **核心优势** - **零运行时开销**:静态多态无需虚函数表(vtable)。 - **编译时多态**:类型检查和优化在编译阶段完成。 - **链式调用支持**:基类方法返回派生类引用,支持链式语法(如`obj.func1().func2()`)[^1]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

2301_80355452

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值