类模板(Class Template)是C++中一种强大的特性,它允许创建可以适用于不同数据类型的通用类。类模板是用于生成类的模板,其中的数据类型可以在实例化时指定。
类模板和函数模板的定义和使用基本是一样的,如何定义函数模板,就如何定义类模板。但是类模板与函数模板还是有点区别的:
类模板不能自动推导类型。
template
class NumberOperator {
public:
T1 num1;
T2 num2;
void cal() {
cout << num1 + num2 << endl;
}
};
int main() {
//创建对象,不能类型推导,只能自己指定类型
NumberOperator op1;
op1.num1 = 10;
op1.num2 = 20;
op1.cal();
//创建对象
NumberOperator 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 NumberOperator { public: T1 num1; T2 num2; void cal() { cout << num1 + num2 << endl; } }; //参数中明确模板类 void useNumberOperation(NumberOperator & op) { op.cal(); } //参数中使用模板 template void useNumberOperation02(NumberOperator & op) { op.cal(); } int main() { //参数明确模板类调用 NumberOperator op1; op1.num1 = 10; op1.num2 = 20; useNumberOperation(op1); //创建对象 NumberOperator 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 Animal { public: T arg; }; //普通类继承模板类的时候,必须明确指定类型 class Dog :Animal { //这里继承到的arg的数据类型是int }; template 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
class NumberCalculator {
private:
T n1;
M n2;
public:
NumberCalculator() {}
NumberCalculator(T n1, M n2);
void add();
};
// 构造函数类外实现
template
NumberCalculator::NumberCalculator(T n1, M n2) {
this->n1 = n1;
this->n2 = n2;
}
// 普通函数类外实现
template
void NumberCalculator::add() {
cout << n1 + n2 << endl;
}
#include
using namespace std; // 全局友元函数类外实现-03:定义类 template class NumberCalculator; // 全局友元函数类外实现-02:在类之前定义 template void printNumberCalculator(const NumberCalculator & op) { cout << "n1 = " << op.n1 << ", n2 = " << op.n2 << endl; } template 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 NumberCalculator ::NumberCalculator(T n1, M n2) { this->n1 = n1; this->n2 = n2; } template NumberCalculator ::NumberCalculator() = default; int main() { NumberCalculator 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
对象的私有成员。