C++泛型编程(模板)
1、C++泛型(模板)介绍
C++模板是C++语言中的一个特性,用于实现泛型编程。模板可以让我们编写通用的代码,能够处理多种不同类型的数据,而无需为每种类型编写重复的代码。通过模板,可以将类型参数化,使得代码更加灵活和可重用。使用模板的主要原因有以下几点:
(1)提高代码的复用性
通过使用模板,我们可以编写通用的代码,可以适用于多种不同的数据类型。这样可以减少代码冗余,提高代码的复用性。
(2)提高代码的可读性和可维护性
模板使得代码更加清晰、简洁,提供了更好的可读性和可维护性。由于代码是通用的,因此更容易理解和修改。
(3)提供更高的性能
通过模板生成的代码是在编译时进行实例化的,而不是在运行时。这样可以避免运行时的类型检查和转换,提高代码的性能。
下面是一个关于电脑的例子,演示了模板的使用:
#include <iostream>
2、函数模板
C++函数模板是一种特殊的函数,可以用于处理多种不同类型的数据。函数模板的定义以关键字`template`开头,后面跟上模板参数列表和函数定义。
函数模板的使用通过实例化来实现,即在调用函数时,根据传入的参数类型,编译器会自动选择合适的函数模板进行实例化。
下面是五个关于函数模板的例子,演示了函数模板的定义和使用:
示例-1:求两个数的最大值
#include <iostream>
template<typename T>
T max(T &a, T &b) {
return (a > b) ? a : b;
}
int main() {
int a = 10, b = 20;
cout << "Max: " << max(a, b) << endl;
double x = 3.14, y = 2.71;
cout << "Max: " << max(x, y) << endl;
return 0;
}
在这个例子中,我们定义了一个函数模板max(),用于求两个数的最大值。在main()函数中,我们分别使用了int类型和double类型的参数调用了max()函数模板。
示例-2:求数组的平均值
#include <iostream>
template<typename T, int N>
T average(T arr[N]) {
T sum = arr[0];
for (int i = 1; i < N; i++) {
sum += arr[i];
}
return sum / N;
}
int main() {
int arr1[] = {1, 2, 3, 4, 5};
cout << "Average: " << average<int, 5>(arr1) << endl;
double arr2[] = {1.1, 2.2, 3.3, 4.4, 5.5};
cout << "Average: " << average<double, 5>(arr2) << endl;
return 0;
}
在这个例子中,我们定义了一个函数模板average(),用于求数组的平均值。模板参数`T`表示数组元素的类型,N表示数组的长度。
在main()函数中,我们分别使用了int类型和double类型的数组调用了average()函数模板。
(1) 函数模板隐式实例化
隐式实例化是在调用该函数时,根据传入参数的类型自动实例化模板生成对应的具体函数。
示例-1:模板函数实现加法操作
#include <iostream>
template<typename T>
T Add(T a, T b) {
return a + b;
}
int main() {
int a = 1, b = 2;
float c = 1.5, d = 2.5;
cout << "int add result is: " << Add(a, b) << endl;
cout << "float add result is:" << Add(c, d) << endl;
return 0;
}
在上面的例子中,我们定义了一个模板函数Add,该函数接受两个相同类型的参数,并返回它们的和。在main函数中,我们分别传入整型和浮点型参数调用了Add函数,由于编译器会根据传入参数的类型自动实例化模板,所以在编译时会生成两个具体函数Add<int>和Add<float>。因此,上述代码输出的结果分别是int加法结果: 3和float加法结果: 4。
示例-2:模板函数实现最大值比较
template<typename T>
T Max(T a, T b) {
return a > b ? a : b;
}
int main() {
int a = 1, b = 2;
float c = 1.5, d = 2.5;
cout << "int result is: " << Max(a, b) << endl;
cout << "floa result is: " << Max(c, d) << endl;
return 0;
}
上述代码中,我们定义了一个模板函数Max,它接受两个相同类型的参数,并返回它们中较大的值。在main函数中,我们分别传入整型和浮点型参数调用了Max函数,编译器会根据传入参数的类型自动实例化模板,生成两个具体函数Max<int>和Max<float>。因此,上述代码输出的结果分别是int最大值: 2和float最大值: 2.5。
(2)函数模板显式实例化
C++函数模板的显式实例化是在编译时手动指定要实例化的模板类型,而不是根据参数类型的隐式推导来实例化模板。
示例-1:模板函数实现打印数组元素
#include <iostream>
template<typename T>
void PrintArray(T arr[], int size) {
for (int i = 0; i < size; i++) {
cout << arr[i] << " ";
}
cout << endl;
}
int main() {
int intArr[] = {1, 2, 3, 4, 5};
float floatArr[] = {1.1, 2.2, 3.3, 4.4, 5.5};
cout << "int array is:";
PrintArray<int>(intArr, 5);
cout << "float array is:";
PrintArray<float>(floatArr, 5);
return 0;
}
在上面的例子中,我们定义了一个模板函数PrintArray,该函数接受一个数组和数组的大小作为参数,用于打印数组的元素。在main函数中,我们分别传入整型数组和浮点型数组调用了PrintArray函数,并通过显式实例化模板指定了模板类型为int和float。这样,编译器会根据指定的模板类型生成对应的具体函数,因此,上述代码输出的结果分别是:
打印整型数组: 1 2 3 4 5
打印浮点型数组: 1.1 2.2 3.3 4.4 5.5
示例-2:模板函数实现求和
template<typename T>
T Sum(T arr[], int size) {
T sum = 0;
for (int i = 0; i < size; i++) {
sum += arr[i];
}
return sum;
}
int main() {
int intArr[] = {1, 2, 3, 4, 5};
float floatArr[] = {1.1, 2.2, 3.3, 4.4, 5.5};
cout << "in array sum: " << Sum<int>(intArr, 5) << endl;
cout << "float array sum: " << Sum<float>(floatArr, 5) << endl;
return 0;
}
在上述代码中,我们定义了一个模板函数Sum,该函数接受一个数组和数组的大小作为参数,并返回数组元素的和。在main函数中,我们分别传入整型数组和浮点型数组调用了Sum函数,并通过显式实例化模板指定了模板类型为int和float。这样,编译器会根据指定的模板类型生成对应的具体函数,因此,上述代码输出的结果分别是:
整型数组求和: 15
浮点型数组求和: 16.5
(3)函数模板特化
C++函数模板的特化是针对特定类型的模板参数,为其提供单独的实现。特化可以分为部分特化和完全特化两种。
部分特化是在模板参数的基础上进一步约束条件,为满足特定条件的模板参数提供单独的实现。完全特化是针对某个特定类型的模板参数提供单独的实现。下面是两个例子:
示例-1:
部分特化:模板函数实现打印数组元素
#include <iostream>
template<typename T, int SIZE>
struct ArrayPrinter {
static void Print(T arr[]) {
for (int i = 0; i < SIZE; i++) {
cout << arr[i] << " ";
}
cout << endl;
}
};
template<int SIZE>
struct ArrayPrinter<char, SIZE> {
static void Print(char arr[]) {
for (int i = 0; i < SIZE; i++) {
cout << arr[i];
}
cout << endl;
}
};
int main() {
int intArr[] = {1, 2, 3, 4, 5};
char charArr[] = {'H', 'e', 'l', 'l', 'o'};
cout << "int array is: ";
ArrayPrinter<int, 5>::Print(intArr);
cout << "char array is: ";
ArrayPrinter<char, 5>::Print(charArr);
return 0;
}
在上面的例子中,我们定义了一个模板结构体ArrayPrinter,该结构体包含一个静态成员函数Print,用于打印数组的元素。针对一般的模板参数类型T,我们提供了默认的实现,遍历数组并打印每个元素。而当模板参数类型为`char`时,我们进行了部分特化,重写了Print函数,只打印字符而不输出空格。在main函数中,我们分别传入整型数组和字符数组调用了ArrayPrinter的Print函数,并通过部分特化指定了模板参数类型为char的特殊实现。这样,上述代码输出的结果分别是:
打印整型数组: 1 2 3 4 5
打印字符数组: Hello
示例-2:
完全特化:模板函数实现求和
#include <iostream>
template<typename T>
struct Sum {
static T Calculate(T arr[], int size) {
T sum = 0;
for (int i = 0; i < size; i++) {
sum += arr[i];
}
return sum;
}
};
template<>
struct Sum<char> {
static int Calculate(char arr[], int size) {
int sum = 0;
for (int i = 0; i < size; i++) {
sum += arr[i];
}
return sum;
}
};
int main() {
int intArr[] = {1, 2, 3, 4, 5};
char charArr[] = {'H', 'e', 'l', 'l', 'o'};
cout << "int array sum: " << Sum<int>::Calculate(intArr, 5) << endl;
cout << "char array sum: " << Sum<char>::Calculate(charArr, 5) << endl;
return 0;
}
在上述代码中,我们定义了一个模板结构体Sum,该结构体包含一个静态成员函数 Calculate,用于计算数组元素的和。针对一般的模板参数类型T,我们提供了默认的实现,遍历数组并累加每个元素。而当模板参数类型为char时,我们进行了完全特化,重写了Calculate函数,将字符强制转换为整型并进行累加。在main函数中,我们分别传入整型数组和字符数组调用了Sum的Calculate函数,并通过完全特化指定了模板参数类型为char的特殊实现。这样,上述代码输出的结果分别是:
整型数组求和: 15
字符数组求和: 500
(4)函数模板重载
C++函数模板的重载是指在模板参数相同或相似的情况下,根据参数类型的不同,为同一个函数模板提供不同的实现。下面是一个简单的例子:
#include <iostream>
template<typename T>
void Print(T value) {
std::cout << "普通版本: " << value << std::endl;
}
template<typename T>
void Print(T arr[], int size) {
std::cout << "数组版本: ";
for (int i = 0; i < size; i++) {
std::cout << arr[i] << " ";
}
std::cout << std::endl;
}
int main() {
int intValue = 10;
float floatValue = 3.14;
int intArr[] = {1, 2, 3, 4, 5};
Print(intValue);
Print(floatValue);
Print(intArr, 5);
return 0;
}
在上面的例子中,我们定义了一个函数模板Print,用于打印参数的值。首先,我们提供了一个普通版本的模板函数,用于打印单个值。然后,我们又重载了该模板函数,并提供了一个数组版本的实现,用于打印整型数组的元素。在main函数中,我们分别调用了Print函数,并传入了不同的参数类型。根据参数类型的不同,编译器会选择调用对应的重载版本。这样,上述代码输出的结果分别是:
普通版本: 10
普通版本: 3.14
数组版本: 1 2 3 4 5
通过这个例子,我们可以看到C++函数模板的重载可以根据参数类型的不同,为同一个函数模板提供不同的实现。重载可以提高代码的复用性和可读性,使得函数模板能够适用于更多的场景。
3、类模板
(1)类模板举例
C++类模板是一种通用的类定义,它可以根据不同的类型参数生成不同的具体类。
#include <iostream>
template<typename T>
class Stack {
private:
T* data; // 存储数据的数组
int top; // 栈顶指针
int size; // 栈的大小
public:
Stack(int s) {
size = s;
data = new T[size];
top = -1;
}
~Stack() {
delete[] data;
}
void Push(T value) {
if (top == size - 1) {
cout << "The stack is full !" << endl;
return;
}
top++;
data[top] = value;
}
T Pop() {
if (top == -1) {
cout << "The stack is empty !" << endl;
return T();
}
top--;
return data[top + 1];
}
};
int main() {
Stack<int> intStack(5);
intStack.Push(1);
intStack.Push(2);
intStack.Push(3);
cout << intStack.Pop() << endl;
cout << intStack.Pop() << endl;
Stack<char> charStack(3);
charStack.Push('a');
charStack.Push('b');
cout << charStack.Pop() << endl;
cout << charStack.Pop() << endl;
return 0;
}
在上面的例子中,我们定义了一个类模板Stack,用于实现一个栈。该模板可以根据不同的类型参数生成不同的栈类。在栈类中,我们使用一个数组data来存储数据,top表示栈顶指针,size表示栈的大小。我们提供了一些基本的操作,如入栈Push和出栈Pop。在main函数中,我们分别创建了一个int类型的栈和一个char类型的栈,并对它们进行了一些操作。根据不同的类型参数,编译器会生成对应的具体类,从而实现不同类型的栈。
通过这个例子,我们可以看到C++类模板可以根据不同的类型参数生成不同的具体类,实现了代码的通用性。类模板使得我们可以编写通用的类定义,适用于多种数据类型。
(2) 类模板隐式实例化
当我们使用C++类模板创建对象时,编译器会根据对象的类型参数自动实例化具体的类,这个过程称为隐式实例化。下面是一个简单的例子,展示了隐式实例化的过程:
#include <iostream>
#include <cstring>
using namespace std;
template<typename T>
class Computer {
private:
T brand;
int price;
public:
Computer(T b, int p) : brand(b), price(p) {}
void Display() {
cout << "Brand: " << brand << endl;
cout << "Price: " << price << endl;
}
};
int main() {
Computer<string> laptop("Lenovo", 1000);
laptop.Display();
Computer<int> desktop(123, 2000);
desktop.Display();
return 0;
}
在上面的例子中,我们定义了一个类模板Computer,用于表示电脑对象。该类模板有两个成员变量:brand表示品牌,price表示价格。我们提供了构造函数来初始化对象,并提供了一个Display函数来打印电脑的品牌和价格。
在main函数中,我们根据需要创建了两个不同类型的电脑对象。laptop对象具有string类型的品牌和int类型的价格,而desktop对象则具有int类型的品牌和价格。在创建这些对象时,编译器会根据对象的类型参数自动实例化具体的类。
通过隐式实例化,我们可以根据不同的类型参数创建不同的具体类对象,而无需显式地为每个具体类型编写类定义。这样可以提高代码的重用性和可维护性,使得我们可以更灵活地处理不同类型的数据。
(3) 类模板显式实例化
C++类模板的显式实例化是指在编译器需要使用具体类型的模板实例时,通过显式声明来告诉编译器实例化模板。这样可以在编译时生成特定类型的模板代码,提高代码执行效率和减少代码体积。
下面是一个关于电脑的简单例子,展示了如何使用C++类模板的显式实例化。假设我们有一个名为Computer的类模板,用于表示电脑,并包含了一些基本的属性和方法。
template <typename T, typename U>
class Computer {
public:
T model;
U price;
Computer(T m, U p) : model(m), price(p) {}
void displayInfo() {
cout << "Model: " << model << endl;
cout << "Price: " << price << endl;
}
};
int main() {
// 显式实例化Computer<int, float>模板
Computer<int, float> computer1(1234, 999.99);
computer1.displayInfo();
// 显式实例化Computer<std::string, double>模板
Computer<string, double> computer2("MacBook Pro", 1999.99);
computer2.displayInfo();
return 0;
}
在上述例子中,我们在主函数中使用Computer<int, float>和Computer<std::string, double>来显式实例化了Computer类模板,分别代表了一个型号为1234,价格为999.99的整型电脑和一个型号为"MacBook Pro",价格为1999.99的字符串和浮点型电脑。然后,我们调用了displayInfo()方法来显示电脑的型号和价格。
通过显式实例化,编译器将为每个具体的类型生成独立的模板代码。这样可以确保在编译时生成特定类型的代码,提高执行效率和减少代码体积。
(4) 类模板的特化
C++类模板的特化是指针对某些特定类型,提供与通用模板不同的实现。通过特化,我们可以为特定类型定制化的实现,以满足特殊需求。
下面是一个关于书籍的简单例子,展示了如何使用C++类模板的特化。假设我们有一个名为Book的类模板,用于表示书籍,并包含了一些基本的属性和方法。我们将为书籍类型提供特化的实现。
首先,我们定义一个Book类模板,定义了一个模板参数T,表示书籍的类型:
template <typename T>
class Book {
public:
T title;
std::string author;
double price;
Book(T t, std::string a, double p) : title(t), author(a), price(p) {}
void displayInfo() {
std::cout << "Title: " << title << std::endl;
std::cout << "Author: " << author << std::endl;
std::cout << "Price: " << price << std::endl;
}
};
然后,我们为特定类型的书籍提供特化的实现,例如儿童书籍类型。在特化中,我们将模板参数T指定为std::string,以表示书籍的标题:
template <>
class Book<std::string> {
public:
std::string title;
std::string author;
double price;
int ageLimit;
Book(std::string t, std::string a, double p, int age) : title(t), author(a), price(p), ageLimit(age) {}
void displayInfo() {
std::cout << "Title: " << title << std::endl;
std::cout << "Author: " << author << std::endl;
std::cout << "Price: " << price << std::endl;
std::cout << "Age Limit: " << ageLimit << std::endl;
}
};
最后,在主函数中使用Book类模板和其特化的演示:
int main() {
Book<std::string> novel("Pride and Prejudice", "Jane Austen", 19.99, 0);
novel.displayInfo();
Book<int> textbook(1234567890, "John Smith", 59.99);
textbook.displayInfo();
return 0;
}
在上述例子中,我们分别创建了一本儿童书籍和一本教材的实例,通过Book类模板和其特化来表示不同类型的书籍。对于儿童书籍类型,我们使用Book<std::string>来创建实例,并提供了特化的实现以表示书籍的标题和年龄限制。对于教材类型,我们使用Book<int>来创建实例,并使用通用模板实现。
通过特化,我们可以根据不同的类型提供定制化的实现,以满足特殊需求。这样可以使代码更具灵活性和复用性。
(5)模板的重载和优先级
C++模板的重载指的是根据模板参数的类型或数量的不同,提供多个模板定义,并根据调用时的实际参数类型或数量来选择合适的模板进行实例化。C++模板的重载是通过类型或数量的差异来决定的,而不是通过函数参数的差异来决定的。
下面是一个关于书籍的简单例子,展示了C++模板的重载和优先级。假设我们有一个名为Book的类模板,用于表示书籍的标题和作者。我们将为不同类型的书籍提供不同的模板定义,并展示它们的优先级。
首先,我们定义一个通用的Book类模板,可以接受任何类型的标题和作者:
template <typename T, typename U>
class Book {
public:
T title;
U author;
Book(T t, U a) : title(t), author(a) {}
void displayInfo() {
cout << "Title: " << title << endl;
cout << "Author: " << author << endl;
}
};
然后,我们为特定类型的书籍提供重载的模板定义,例如儿童书籍类型和教材类型。在重载模板中,我们可以针对不同的类型提供不同的实现:
template <typename T>
class Book<T, std::string> {
public:
T title;
std::string author;
Book(T t, std::string a) : title(t), author(a) {}
void displayInfo() {
cout << "Title: " << title << endl;
cout << "Author: " << author << endl;
cout << "This is a children's book." << endl;
}
};
template <typename T>
class Book<std::string, T> {
public:
std::string title;
T author;
Book(std::string t, T a) : title(t), author(a) {}
void displayInfo() {
cout << "Title: " << title << endl;
cout << "Author: " << author << endl;
cout << "This is a textbook." << endl;
}
};
最后,在主函数中使用Book类模板和其重载的演示:
int main() {
Book<std::string, std::string> novel("Pride and Prejudice", "Jane Austen");
novel.displayInfo();
Book<int, std::string> childrenBook(1234567890, "Dr. Seuss");
childrenBook.displayInfo();
Book<std::string, double> textbook("C++ Programming", 59.99);
textbook.displayInfo();
return 0;
}
在上述例子中,我们分别创建了一本小说、一本儿童书籍和一本教材的实例,通过Book类模板和其重载来表示不同类型的书籍。对于小说类型,我们使用Book<std::string, std::string>来创建实例,并使用通用模板实现。对于儿童书籍类型,我们使用Book<int, std::string>来创建实例,并使用特定类型的重载模板实现。对于教材类型,我们使用Book<std::string, double>来创建实例,并使用特定类型的重载模板实现。
通过模板的重载和优先级,我们可以根据不同的类型提供不同的实现,以满足特殊需求。当调用模板函数时,编译器会根据实际参数类型和数量的匹配来选择合适的模板进行实例化。
(6)模板的嵌套
C++模板的嵌套指的是在一个模板中使用另一个模板作为参数或返回类型。通过模板的嵌套,我们可以构建更复杂的数据结构或函数,实现更灵活的功能。
下面是一个关于书籍的简单例子,展示了C++模板的嵌套。假设我们有一个名为Book的类模板,用于表示书籍的标题和作者。然后,我们定义一个名为Library的类模板,用于表示图书馆,其中包含多本书籍。在Library类模板中,我们使用了嵌套的Book类模板作为成员变量。
首先,我们定义Book类模板:
template <typename T, typename U>
class Book {
public:
T title;
U author;
Book(T t, U a) : title(t), author(a) {}
void displayInfo() {
cout << "Title: " << title << endl;
cout << "Author: " << author << endl;
}
};
然后,我们定义Library类模板,并使用嵌套的Book类模板作为成员变量:
template <typename T, int size>
class Library {
public:
Book<T, string> books[size]; // 使用嵌套的Book类模板作为成员变量
void displayBooks() {
for (int i = 0; i < size; i++) {
cout << "Book " << i+1 << ":" << endl;
books[i].displayInfo();
cout << endl;
}
}
};
最后,在主函数中使用Library类模板的演示:
int main() {
Library< string, 3> library;
Book< string, string> book1("Pride and Prejudice", "Jane Austen");
Book< string, string> book2("To Kill a Mockingbird", "Harper Lee");
Book< string, string> book3("1984", "George Orwell");
library.books[0] = book1;
library.books[1] = book2;
library.books[2] = book3;
library.displayBooks();
return 0;
}
在上述例子中,我们定义了一个图书馆类模板Library,并使用嵌套的Book类模板作为成员变量。Library类模板接受两个参数,一个是书籍的类型T,一个是图书馆的大小size。在主函数中,我们创建了一个Library<string, 3>类型的实例,表示一个可以容纳3本字符串类型书籍的图书馆。
通过嵌套的Book类模板,我们可以在Library类模板中存储多本书籍,并通过displayBooks函数来展示图书馆中的所有书籍。
通过模板的嵌套,我们可以构建更复杂的数据结构或函数,实现更灵活的功能。在上述例子中,图书馆类模板使用了嵌套的书籍类模板作为成员变量,使得图书馆可以存储不同类型的书籍,并且可以根据实际需求进行扩展。
(7)函数成员模板
C++函数成员模板是一种将模板应用于类的成员函数的技术。它允许在类中定义通用的函数成员,可以处理不同类型的参数,提高代码的复用性和灵活性。
下面是一个关于书籍的简单例子,展示了C++函数成员模板的使用。假设我们有一个名为Book的类,用于表示书籍的标题和作者。然后,我们定义一个名为Library的类,其中包含一个存储书籍的向量容器。在Library类中,我们使用了函数成员模板来实现添加和显示书籍的功能。
首先,我们定义Book类:
class Book {
public:
std::string title;
std::string author;
Book(std::string t, std::string a) : title(t), author(a) {}
void displayInfo() {
std::cout << "Title: " << title << std::endl;
std::cout << "Author: " << author << std::endl;
}
};
然后,我们定义Library类,并使用函数成员模板来实现添加和显示书籍的功能:
class Library {
private:
std::vector<Book> books;
public:
template <typename T, typename U>
void addBook(T t, U u) {
Book book(t, u);
books.push_back(book);
}
void displayBooks() {
for (const auto& book : books) {
book.displayInfo();
std::cout << std::endl;
}
}
};
最后,在主函数中使用Library类的演示:
int main() {
Library library;
library.addBook("Pride and Prejudice", "Jane Austen");
library.addBook("To Kill a Mockingbird", "Harper Lee");
library.addBook("1984", "George Orwell");
library.displayBooks();
return 0;
}
在上述例子中,我们定义了一个图书馆类Library,并使用函数成员模板addBook来实现添加书籍的功能。addBook函数接受两个参数,分别用于表示书籍的标题和作者。在函数体内,我们根据传入的参数创建一个Book对象,并将其添加到books容器中。
通过函数成员模板的使用,我们可以在Library类中定义通用的函数成员,可以处理不同类型的参数。在上述例子中,addBook函数可以接受不同类型的参数(例如std::string),使得图书馆可以添加不同类型的书籍。
函数成员模板是C++中强大的特性之一,它提供了更灵活的方式来定义类的成员函数,可以处理不同类型的参数,提高了代码的复用性和灵活性。
(8)对象成员模板
C++对象成员模板是一种将模板应用于类的成员变量的技术。它允许在类中定义通用的成员变量,可以处理不同类型的数据,提高代码的复用性和灵活性。
下面是一个关于书籍的简单例子,展示了C++对象成员模板的使用。假设我们有一个名为Book的类,用于表示书籍的标题和作者。然后,我们定义一个名为Library的类,其中包含一个模板成员变量book,用于存储不同类型的书籍。
首先,我们定义Book类:
class Book {
public:
std::string title;
std::string author;
Book(std::string t, std::string a) : title(t), author(a) {}
void displayInfo() {
std::cout << "Title: " << title << std::endl;
std::cout << "Author: " << author << std::endl;
}
};
然后,我们定义Library类,并使用对象成员模板来实现存储和显示书籍的功能:
template <typename T>
class Library {
private:
T book;
public:
Library(T b) : book(b) {}
void displayBookInfo() {
book.displayInfo();
}
};
最后,在主函数中使用Library类的演示:
int main() {
Book book1("Pride and Prejudice", "Jane Austen");
Book book2("To Kill a Mockingbird", "Harper Lee");
Library<Book> library1(book1);
Library<Book> library2(book2);
library1.displayBookInfo();
std::cout << std::endl;
library2.displayBookInfo();
return 0;
}
在上述例子中,我们定义了一个图书馆类Library,并使用对象成员模板来实现存储不同类型的书籍的功能。Library类的模板参数T表示存储的书籍类型。在类中,我们定义了一个模板成员变量book,用于存储书籍对象。在displayBookInfo函数中,我们调用book的displayInfo函数来显示书籍的信息。
通过对象成员模板的使用,我们可以在Library类中定义通用的成员变量,可以处理不同类型的数据。在上述例子中,Library类可以存储不同类型的书籍对象,并通过displayBookInfo函数来显示书籍的信息。
(9)模板参数
C++模板参数是一种将通用代码应用于不同类型的数据的技术。通过使用模板参数,我们可以编写通用的代码,可以适用于多种数据类型,提高代码的复用性和灵活性。
下面是一个关于书籍的简单例子,展示了C++模板参数的使用。假设我们有一个名为Book的类,用于表示书籍的标题和作者。然后,我们定义一个名为Library的类模板,其中的模板参数T用于表示存储的书籍类型。
首先,我们定义Book类:
class Book {
public:
std::string title;
std::string author;
Book(std::string t, std::string a) : title(t), author(a) {}
void displayInfo() {
std::cout << "Title: " << title << std::endl;
std::cout << "Author: " << author << std::endl;
}
};
然后,我们定义Library类模板,并使用模板参数T来表示存储的书籍类型:
template <typename T>
class Library {
private:
T book;
public:
Library(T b) : book(b) {}
void displayBookInfo() {
book.displayInfo();
}
};
最后,在主函数中使用Library类模板的演示:
int main() {
Book book1("Pride and Prejudice", "Jane Austen");
Book book2("To Kill a Mockingbird", "Harper Lee");
Library<Book> library1(book1);
Library<Book> library2(book2);
library1.displayBookInfo();
std::cout << std::endl;
library2.displayBookInfo();
return 0;
}
在上述例子中,我们定义了一个图书馆类模板Library,并使用模板参数T来表示存储的书籍类型。在Library类的定义中,我们使用T类型的成员变量book来存储书籍对象。在displayBookInfo函数中,我们调用book的displayInfo函数来显示书籍的信息。
通过模板参数的使用,我们可以在Library类模板中定义通用的代码,可以适用于不同类型的书籍。在上述例子中,Library类模板可以存储不同类型的书籍对象,并通过displayBookInfo函数来显示书籍的信息。
C++模板参数是一项强大的特性,它允许我们编写通用的代码来处理不同类型的数据,提高了代码的复用性和灵活性。