C++ template 可变参类模板

类模板参数展开

看一个可变参类模板的范例。先写一个可变参类模板的偏特化

template<typename First, typename... Others>
class myclasst<First, Others...> : private myclasst<Others...> //偏特化
{

}

注意观察上面的代码,观察继承的是谁,模板参数也是分开成一个和一包,这种写法比较固定。

如果此时编译,会报错,因此会写一个泛化版本的类模板,然后才能写特化版本的类模板。所以,在上面代码面前添加代码:

template<typename ...Args>
class myclasst
{
   public:
	 myclasst()
	{
		printf("myclasst::myclasst()泛化版本执行了,this = %p\n", this);
	}
};

现在编译就不会报错了,实际上也有人这样写:

template<typename ...Args> class myclasst;

这里是只写类模板的声明而不写成类模板定义。

现在继续改造上面的可变参类模板的偏特化写法,在其中增加构造函数以及一个成员变量:

template<typename First, typename... Others>
class myclasst<First, Others...> : private myclasst<Others...> //偏特化
{
	public:
		myclasst() :m_i(0)
		{
			printf("myclasst::myclasst()偏特化版本执行了,this = %p,sizeof...(Others)=%d\n", 
              this, sizeof...(Others));
		}
}

然后改造下主模板的定义,也加入一个构造函数:

template<typename ...Args>
class myclasst
{
	public:
		myclasst()
		{
			printf("myclasst::myclasst()泛化版本执行了,this = %p\n", this);
		}
};

在main函数中添加代码:

myclass<int,flaot,double>myc;

运行程序如下:

myclasst<>::myclasst()特殊的特化版本执行了,this = 010FFE70
myclasst::myclasst()偏特化版本执行了,this = 010FFE70,sizeof...(Others)=0
myclasst::myclasst()偏特化版本执行了,this = 010FFE70,sizeof...(Others)=1
myclasst::myclasst()偏特化版本执行了,this = 010FFE70,sizeof...(Others)=2

这里执行了4个构造函数,系统实例化出了4个类,先来说其中3个类,因为源码分析不难。

    执行代码myclass<int,flaot,double>myc;时,系统会去实例化3个类型模板参数的类模板,根据写法class myclasst<First, Others...> : private myclasst<Others...>,他继承的是两个类型模板参数的类模板,而两个类型模板参数的类模板继承的是一个类型模板参数的类模板,因此,系统首先会实例化带一个类型模板参数的类模板,然后实例化带两个类型模板参数的类模板,最后实例化带3个类型模板参数。

  结合刚才的程序的运行结果,编译器遇到带0个模板参数的类模板的时候,就停止类模板参数的继承,同时带0个模板参数的类模板,就停止类模板的继承,同时,这种带0个模板参数的类模板是通过myclass的泛化版本实例化的。

完整代码:

namespace _nmsp5
{
	//主模板定义(泛化版本的类模板)
	template<typename ...Args>
	class myclasst
	{
	public:
		myclasst()
		{
			printf("myclasst::myclasst()泛化版本执行了,this = %p\n", this);
		}
	};

	template<> class myclasst<>  //一个特殊的特化版本
	{
	public:
		myclasst()
		{
			printf("myclasst<>::myclasst()特殊的特化版本执行了,this = %p\n", this);
		}
	};

	template<typename First, typename... Others>
	class myclasst<First, Others...> : private myclasst<Others...> //偏特化
	{
	public:
		myclasst() :m_i(0)
		{
			printf("myclasst::myclasst()偏特化版本执行了,this = %p,sizeof...(Others)=%d\n", this, sizeof...(Others));
		}

		//注意这第二个参数,这一包东西的写法
		myclasst(First parf, Others... paro) :m_i(parf), myclasst<Others...>(paro...)
		{
			cout << "-----------------begin------------------" << endl;
			printf("myclasst::myclasst(parf,...paro)执行了,this = %p\n", this);
			cout << "m_i = " << m_i << endl;
			cout << "-----------------end------------------" << endl;
		}
		First m_i;
	};

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
#include<iostream> using namespace std; class student; class teacher { public: int a = 1; student *p; teacher(int a); ~teacher(); }; teacher::teacher(int a) :a(a) { cout << "teacher构造函数调用" << endl; ///p = new student; } teacher::~teacher() { cout << "teacher析构函数调用" << endl; } class student { public: //友元函数可以访问类中的公有和私有成员,不可以访问保护成员 friend void func2(student &s); friend class teacher; int a = 10; student(int x); ~student(); void func3(); private: int b = 20; }; student::student(int x) :a(x) { cout << "student 构造函数调用1" << endl; } student::~student() { cout << "student 析构函数调用!" << endl; } void student::func3() { cout << b << endl; } void func1() { student s1(100); cout << s1.a << endl; s1.func3(); func2(s1); cout << s1.a << endl; } //友元函数,全局函数做友元 //在形中加入const防止传入的数被改变,不加const则可以改变 void func2( student &s) { //传入普通类对象不可以改变类中的值,只能改变形类的值 /*s.a = 123; cout<<s.a << endl; cout << s.b << endl;*/ ////传入指针可以改变类的值 /*s->a = 1000; s->b = 123; cout << s->a << endl; cout << s->b << endl;*/ ///传入引用也可以改变类中的值 //s.a = 12345; //s.b = 123456; cout << s.a << endl; cout << s.b << endl; } //类做友元 void func3() { student s1(10); cout << s1.a << endl; teacher t1(100); cout << t1.a << endl; cout << t1.p->a<< endl; } int main() { //成员函数做友元 //func1(); //类做友元 func3(); system("pause"); return 0; }
06-08
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

水火汪

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

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

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

打赏作者

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

抵扣说明:

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

余额充值