C++类模板

C++模板是泛型编程的基础,在C++中模板包括:

类模板

定义

template <class T>
类声明和定义

简单使用

template <class nameType, class ageType>
class Person
{
public:
	Person(nameType name, ageType age)
	{
		this->mName = name;
		this->mAge = age;
	}
	void showPerson()
	{
		cout << "name = " << this->mName << ",age = " << this->mAge << endl;
	}
	nameType mName;
	ageType	mAge;
};

void main()
{
	Person<string, string> person("Angel", "999");
	person.showPerson();
}

类模板和函数模板的语法是类似的,更多使用可参考函数模板的内容。

类模板和函数模板的区别

  • 类模板不能使用自动类型推导的调用方式
  • 类模板的模板参数列表可以有默认类型参数

示例:

template <class nameType, class ageType = int>  //模板参数列表设置默认类型
class Person
{
public:
	Person(nameType name, ageType age)
	{
		this->mName = name;
		this->mAge = age;
	}
	void showPerson()
	{
		cout << "name = " << this->mName << ",age = " << this->mAge << endl;
	}
	nameType mName;
	ageType	mAge;
};

void main()
{
	//Person person("Angel", "999"); //错误的
	Person<string> p1("ai", 10);  //第二个模板参数使用默认数据类型
	p1.showPerson();

	Person<string,string> p2("ai", "十岁");  //第二个模板参数使用显式指定类型参数
	p2.showPerson();
}

类模板成员函数创建时机

  • 类模板的成员函数只有程序中使用到,编译器才会真正创建相应的函数

示例:

class myShow1
{
public:
	void show1()
	{
		cout << "show1" <<endl;
	}
};

class myShow2
{
public:
	void show2()
	{
		cout << "show2" <<endl;
	}
};

template <class T>
class MyClass
{
	T obj;
public:
 	//成员函数
	void fun1() 
	{
		obj.show1();
	}
	void fun2()
	{
		obj.show2();
	}
};

void main()
{
	MyClass<myShow1> myclass;
	myclass.fun1();
	//myclass.fun2();  //使用到show2,编译根据指定的类型去创建该函数,此时则会报错“show2”: 不是“myShow1”的成员
	//屏蔽此处调用则程序正常,即不使用,成员函数就不创建
}

类模板对象做函数参数

类模板实例化出的对象,向函数传参的方式:

  • 指定传入的类型 — 直接显式指定对象的数据类型
  • 参数模板化 — 将对象中的参数变为模板进行传递
  • 整个类模板化 — 将这个对象类型 模板化进行传递

示例:

template <class T1, class T2> 
class Person
{
public:
	Person(T1 name, T2 age)
	{
		m_Name = name;
		m_Age = age;
	}
	void showPerson()
	{
		cout << "name = "  << m_Name << " age = " << m_age << endl;
	}
	T1 m_Name;
	T2 m_Age;
};

//1、指定传入的类型
void showPerson1(Person<string, int> &person)
{
	person.showPerson();
}
//2、参数模板化,实际就是函数模板和类模板结合使用
template <class T1, class T2>
void showPerson2(Person<T1, T2> &person)
{
	cout << typeid(T1).name() << endl;  // 可以查看传入的类型名称
	cout << typeid(T2).name() << endl;
	person.showPerson();
}
//3、整个类模板化,实际就是函数模板和类模板结合使用
template <class T>
void showPerson3(T &person)
{
	cout << typeid(T).name() << endl;
	person.showPerson();
}

void main()
{
	Person<string, int> person("哈哈哈", 456);
	showPerson1(person);
	showPerson2(person);
	showPerson3(person);
}

结论:使用的比较广泛的是第一种,直接指定传入的参数类型。

类模板与继承

  • 继承时直接指定父类(一般不常用,父类则类型指定,则失去模板的意义)
  • 子类也写为类模板,则可以灵活指定父类模板参数类型
template <class T>
class Base
{
	T m_obj;
};

//1、直接指定父类模板参数列表类型
class Son : public Base<int>
{

};

//2、子类也为类模板
template <class T1, class T2>
class Son2 : public Base<T2>
{
public:
	Son2()
	{
		cout << typeid(T1).name() << endl;
		cout << typeid(T2).name() << endl;
	}
};
void main()
{
	Son2<string,int> son2;
	system("pause");
}

类模板成员函数的类外实现

  • 类模板成员函数类外实现需要加上类模板的参数列表,这样编译器才知道函数是类模板成员函数的实现
template<class T1, class T2>
class Person
{
public:
	Person(T1 name, T2 age);
	void ShowPerson();
private:
	T1 m_Name;
	T2 m_Age;
};

template<class T1, class T2, class T3>
class Person1
{
public:
	Person1(T1 name, T2 age);
	void Person(T1 name, T2 age);
	void ShowPerson();
private:
	T1 m_Name;
	T2 m_Age;
	T3 m_Like;
};

template<class T1, class T2>
Person<T1, T2>::Person(T1 name, T2 age)
{
	m_Name = name;
	m_Age = age;
}

template<class T1, class T2>
void Person<T1, T2>::ShowPerson() // 如果不加类模板的参数列表<T1,T2>,则编译器不知道是对person还是person1成员函数的实现
{
	cout << "name = "<< m_Name << endl;
	cout << "age = " << m_Age << endl;
}

void main()
{
	Person<string, int> p1("名字", 10);
	p1.ShowPerson();
	system("pause");
}

类模板的分文件编写

 像普通类分开.h和.cpp分开实现,调用.h使用,调用类模板成员函数编译会提示无法无法解析的外部命令
 问题导致原因:主要是C++的分文件编译导致类模板的成员函数没有创建,具体分析参考https://blog.csdn.net/qq_41929943/article/details/103004083
解决方法

  • 直接包含.cpp文件使用(不常用);
  • 将类模板的声明和实现写到一个文件,文件命名为.hpp(约定俗成的后缀);

类模板与友元函数

  • 全局函数类内实现 ---- 建议使用
  • 全局函数类外实现 ---- 比较复杂,不是必要的话不建议使用

//实现全局函数
template<class T1, class T2> // 因为要用到类模板,所以该函数写成模板函数
void showPerson2(Person<T1, T2> person)
{
	cout << "name = " << person.m_Name << endl; // 访问类的私用成员
	cout << "age = " << person.m_Age << endl;
}

//实现全局函数
template<class T1, class T2,class T3> // 因为要用到类模板,所以该函数写成模板函数
void showPerson2(Person<T1, T2> person)
{
	cout << "name1 = " << person.m_Name << endl; // 访问类的私用成员
	cout << "age1 = " << person.m_Age << endl;
}


template<class T1, class T2>
class Person
{
	//类内实现友元函数,可以访问类的私有成员---比较简单
	friend void showPerson1(Person<T1, T2> person)
	{
		cout << "name = " << person.m_Name << endl;
		cout << "age = " << person.m_Age << endl;
	}

	//类外实现的函数要能放访问类的私有成员,需要声明为类的友元
	//friend void showPerson2(Person<T1, T2> person); //该写法是错的
	template <class T1,class T2,class T3>
	friend void showPerson2<T1,T2,T3>(Person<T1, T2> person); //需要通过showPerson2<>让编译器指定声明为友元的是个模板函数,如果友元函数发生重载,还需要指定类模板参数类别来区别重载的函数

public:
	Person(T1 name, T2 age)
	{
		m_Name = name;
		m_Age = age;
	}
private:
	T1 m_Name;
	T2 m_Age;
};

void main()
{
	Person<string, int> p("小喵", 100);
	showPerson1(p);
	showPerson2<string,int,int>(p);

	system("pause");
}

案例

类模板实现通用数组类

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值