类模板(Class Template)是C++中一种强大的特性,它允许创建可以适用于不同数据类型的通用类。类模板是用于生成类的模板,其中的数据类型可以在实例化时指定。
类模板和函数模板的定义和使用基本是一样的,如何定义函数模板,就如何定义类模板。但是类模板与函数模板还是有点区别的:
类模板不能自动推导类型。
- template<class T1,class T2=int>
- class NumberOperator {
- public:
- T1 num1;
- T2 num2;
-
- void cal() {
- cout << num1 + num2 << endl;
- }
- };
-
- int main() {
-
- //创建对象,不能类型推导,只能自己指定类型
- NumberOperator<int, int> op1;
- op1.num1 = 10;
- op1.num2 = 20;
- op1.cal();
-
- //创建对象
- NumberOperator<double> op2;
- op2.num1 = 3.14;
- op2.num2 = 10;
- op2.cal();
-
- return 0;
- }
这段代码演示了使用类模板
NumberOperator来创建具有不同数据类型的对象。NumberOperator类模板允许您定义两个模板参数T1和T2,其中T2默认为int类型。这样,您可以根据需要选择性地指定类型,或者使用默认类型。在
main函数中,我们创建了两个不同类型的NumberOperator对象:
op1是一个NumberOperator对象,其中T1和T2都被指定为int类型。我们设置了num1和num2的值,然后调用cal函数来计算它们的和,并输出结果。
op2是另一个NumberOperator对象,这次我们只指定了T1为double类型,而T2使用了默认的int类型。同样,我们设置了num1和num2的值,然后调用cal函数来计算它们的和,并输出结果。
template<class T1,class T2=int> class NumberOperator { public: T1 num1; T2 num2; void cal() { cout << num1 + num2 << endl; } }; //参数中明确模板类 void useNumberOperation(NumberOperator<int, int>& op) { op.cal(); } //参数中使用模板 template<class T1,class T2> void useNumberOperation02(NumberOperator& op) { op.cal(); } int main() { //参数明确模板类调用 NumberOperator<int, int> op1; op1.num1 = 10; op1.num2 = 20; useNumberOperation(op1); //创建对象 NumberOperator<double,int> op2; op2.num1 = 3.14; op2.num2 = 10; useNumberOperation02(op2); return 0; }这段代码演示了如何使用参数中明确模板类或使用模板参数的方式来调用
NumberOperator类模板的成员函数。这允许在不同的上下文中使用模板类。在这个代码中:
useNumberOperation函数的参数op是一个明确指定了模板参数类型的NumberOperator类对象。这里我们明确指定了T1和T2为int类型。然后,我们调用op.cal()来计算并输出结果。
useNumberOperation02函数使用了模板参数T1和T2。这意味着您可以在调用时根据需要指定模板参数类型。在main函数中,我们创建了一个NumberOperator对象op2,其中T1明确指定为double类型,而T2使用默认的int类型。然后,我们使用useNumberOperation02(op2)调用该函数,它会计算并输出结果。
//定义模板类 template<class T> class Animal { public: T arg; }; //普通类继承模板类的时候,必须明确指定类型 class Dog :Animal<int> { //这里继承到的arg的数据类型是int }; template<class E> class Person :Animal{ //这里继承到得arg的数据类型是E };
您提供的代码示例演示了如何定义一个模板类
Animal,以及如何创建普通类Dog和Person来继承这个模板类。
Animal是一个模板类,它拥有一个模板类型参数T,该参数可以用于定义类中的成员。
Dog是一个普通类,通过class Dog : Animal继承了模板类Animal,并明确指定了类型参数为int。这意味着Dog类中的arg成员的数据类型是int。
Person也是一个模板类,它继承了模板类Animal,但没有明确指定类型参数,而是使用了E作为类型参数。这使得Person类中的arg成员的数据类型取决于在实例化Person类时传递的类型参数E。
- template<typename T, typename M>
- class NumberCalculator {
- private:
- T n1;
- M n2;
- public:
- NumberCalculator() {}
- NumberCalculator(T n1, M n2);
-
- void add();
- };
- // 构造函数类外实现
- template<typename T, typename M>
- NumberCalculator
::NumberCalculator(T n1, M n2) { - this->n1 = n1;
- this->n2 = n2;
- }
- // 普通函数类外实现
- template<typename T, typename M>
- void NumberCalculator
::add() { - cout << n1 + n2 << endl;
- }
#include using namespace std; // 全局友元函数类外实现-03:定义类 template<typename T, typename M> class NumberCalculator; // 全局友元函数类外实现-02:在类之前定义 template<typename T, typename M> void printNumberCalculator(const NumberCalculator& op) { cout << "n1 = " << op.n1 << ", n2 = " << op.n2 << endl; } template<typename T, typename M> class NumberCalculator { // 全局友元函数类内实现,⽆需进⾏什么处理,直接在这⾥写实现即可。 /* friend void printNumberCalculator(const NumberCalculator& op) { cout << "n1 = " << op.n1 << ", n2 = " << op.n2 << endl; }*/ // 全局友元函数类外实现—01:在函数的后⾯添加⼀对尖括号,表示⼀个模板函数 friend void printNumberCalculator<>(const NumberCalculator& op); private: T n1; M n2; public: NumberCalculator(); NumberCalculator(T n1, M n2); }; template<typename T, typename M> NumberCalculator::NumberCalculator(T n1, M n2) { this->n1 = n1; this->n2 = n2; } template<typename T, typename M> NumberCalculator::NumberCalculator() = default; int main() { NumberCalculator<int, int> op(10, 20); printNumberCalculator(op); return 0; }这段代码演示了如何使用友元函数来访问类模板
NumberCalculator中的私有成员。友元函数可以访问类的私有成员,即使这些私有成员的数据类型是模板参数。以下是代码的解释:
在代码中,首先定义了一个类模板
NumberCalculator,它具有两个模板类型参数T和M,表示类的两个私有成员n1和n2的数据类型。在全局范围内定义了一个友元函数
printNumberCalculator,该函数接受一个NumberCalculator对象作为参数,并用于输出对象的私有成员n1和n2的值。在类模板内,通过
friend关键字声明printNumberCalculator为类模板NumberCalculator的友元函数。在这种情况下,您需要提供额外的<>尖括号,以告诉编译器这是一个模板函数。在
main函数中,我们创建了一个NumberCalculator对象op,并调用printNumberCalculator(op)来输出op对象的私有成员。