Table of contents
(1) The concept of function template
(2) Example of a function template
(3) Matching order of function or function template call statement
(3) Class templates and inheritance
1. Function template
- When designing functions in a program, you may encounter situations where the types of parameters in the functions are different, but the functions that need to be implemented are similar.
- Function overloading can handle this situation.
- In the parameter table of the overloaded function, different types of parameters can be written, so that different situations can be handled.
(1) The concept of function template
- In order to improve efficiency and achieve code reuse, C++ provides a processing mechanism, that is, using function templates .
- Functions are not designed with actual types, but virtual type parameters.
- This saves you from having to write code snippets for each different type.
- Use a function template with a concrete data type when instantiating such a function with an actual type.
- The compiler will use the function template as a template to generate a function, that is, a template function is generated. This process is called function template instantiation.
- The process of function template instantiation is done by the compiler.
- The type of the corresponding data is not given during program design, and the compiler instantiates it according to the actual type during compilation.
(2) Example of a function template
- In fact, a function template is not a concrete function for which the compiler cannot generate executable code.
- After defining a function template, it is just a description of the functional framework of the function. When it is executed, its function will be determined according to the actual parameters passed.
- Function templates can also take multiple type parameters.
Although the usage of function templates is similar to that of functions , there are essential differences between the two , mainly in the following three aspects:
- The function template itself will not generate any object code when compiling, and the object code will only be generated when a specific function instance is generated through the template.
- Function templates that are referenced by multiple source files should be placed in the header file together with the function body, instead of just putting the declaration in the header file like ordinary functions.
- Function pointers can only point to instances of templates, not to templates themselves.
[Example 1] A template function is created
abs
to obtain the absolute value of any type of variable through the template parameter T. Different types of variables are defined in the main function, andabs
their absolute values are output through the function【Example code】
#include <iostream> // 导入 iostream 库 using namespace std; template<typename T> // 创建模板函数 T abs(T x) // 定义模板函数 { return x < 0 ? -x : x; // 使用三目运算符计算绝对值并返回 } int main() // 主函数 { int n = -5; // 初始化变量 n 为 -5 int m = 10; // 初始化变量 m 为 10 double d = -0.5; // 初始化变量 d 为 -0.5 float f = 3.2; // 初始化变量 f 为 3.2 cout << n << "的绝对值是:" << abs(n) << endl; // 输出 n 的绝对值 cout << m << "的绝对值是:" << abs(m) << endl; // 输出 m 的绝对值 cout << d << "的绝对值是:" << abs(d) << endl; // 输出 d 的绝对值 cout << f << "的绝对值是:" << abs(f) << endl; // 输出 f 的绝对值 return 0; // 返回 0 表示执行成功 }
【Code Explanation】
- The program first imports
iostream
the library, which contains standard output tools such asstd::cout
andstd::endl
.- In the template function
abs
, we use a conditional ternary operator to return the absolute value of the passed argument. The parameter of this function is a generic typeT
variable x.- In the main function, we initialize four variables
n
,m
,d
andf
, which are integer-5
, integer,10
double-precision floating-point-0.5
and single-precision floating-point3.2
. Next, we callabs
the function separately to output the absolute value of each variable. Finally, the program executes successfully and returns0
.【Results of the】
- This code creates a template function
abs
to obtain the absolute value of any type of variable through the template parameter T. Different types of variables are defined in the main function, andabs
their absolute values are output through the function.- This shows that template functions work well with variables of many types.
- The output is:
-5的绝对值是:5 10的绝对值是:10 -0.5的绝对值是:0.5 3.2的绝对值是:3.2
[Example 2] Template function
[Example code] In the main function, when abs(n) is called, the compiler deduces that the type parameter T in the template is int according to the type int of the actual parameter n, and then instantiates the function template to generate an instance of the function template abs .
int abs(int x) //定义求整数x的绝对值函数 { return x < 0 ? -x : x; //判断x是否小于0,如果是则取相反数,否则返回x }
【Code Explanation】
- This code defines a function to find the absolute value of an integer
abs
, that is, an integer is passed inx
and its corresponding absolute value is returned. Use the ternary operator to judge, if it isx
less than 0, take the opposite number, otherwise return directlyx
.
[Example 3] Template function
[Example code] When abs(d) is called, a new function is instantiated according to the type double of the actual parameter d.
double abs(double x) //定义求双精度浮点型x的绝对值函数 { return x < 0 ? -x : x; //判断x是否小于0,如果是则取相反数,否则返回x }
【Code Explanation】
- This code defines a function to find the absolute value of a double-precision floating-point number
abs
, that is, a double-precision floating-point number is passed inx
, and its corresponding absolute value is returned. Use the ternary operator to judge, if it isx
less than 0, take the opposite number, otherwise return directlyx
. In fact, a function template is not a concrete function for which the compiler cannot generate executable code. define function moduloBehind the board is just a description of the functional framework of the function. When it is executed, its function will be determined according to the actual parameters passed.
[Example 4] A general function template and a date class, in which the function template can exchange variable values of different types, and the use of the template function Swap under different data types is tested
【Example code】
#include<iostream> //包含标准输入输出流库 using namespace std; template<class T> //定义通用类型模板 void Swap(T &x, T &y) //定义模板函数 Swap,参数为 T 类型引用 x 和 y { T tmp = x; //定义 T 类型变量 tmp,赋值为 x x = y; //把 y 的值赋给 x y = tmp; //把 tmp 的值赋给 y } class myDate //定义 myDate 类 { public: myDate(); //默认构造函数 myDate(int, int, int); //构造函数 void printDate() const; //打印日期信息 private: int year, month, day; //成员变量:年、月、日 }; myDate::myDate() //默认构造函数的实现 { year = 1970; //初始年为 1970 month = 1; //初始月为 1 day = 1; //初始日为 1 } myDate::myDate(int y, int m, int d) //参数构造函数的实现 { year = y; //初始化年份 month = m; //初始化月份 day = d; //初始化日期 } void myDate::printDate() const //打印日期信息 { cout << year << "/" << month << "/" << day << endl; //输出日期 return; //返回空值 } int main() //主函数 { int n = 1, m = 2; //定义两个整型变量 n 和 m,分别赋值为 1 和 2 Swap(n, m); //调用 Swap 函数进行值交换 cout << n << " " << m << endl; //输出交换后的结果 double f = 1.2, g = 2.3; //定义两个双精度浮点数变量 f 和 g,分别赋值为 1.2 和 2.3 Swap(f, g); //调用 Swap 函数进行值交换 cout << f << " " << g << endl; //输出交换后的结果 myDate d1, d2(2000, 1, 1); //定义两个日期对象,d1 默认构造函数创建,d2 利用参数构造函数创建 Swap(d1, d2); //调用 Swap 函数进行值交换 d1.printDate(); //输出日期信息 d2.printDate(); //输出日期信息 return 0; //程序执行成功,返回0 }
【Code Explanation】
- The program defines a general type template
Swap
, and utilizes this template to realize the value exchange in C++, in whichSwap
the variable value exchange of different types can be realized. A class is also definedmyDate
to represent a date, including a constructor, a default constructor, and a function to print date information.main
Create variables of different types in the function, and call theSwap
function for value exchange to show the versatility of this function.#include<iostream>
: Contains the standard input and output stream library.using namespace std;
: Use the namespace of the standard library.template<class T>
: Define a general type template, useclass
ortypename
one of them to declare the type template parameter, the code after the colon is the type name of the template variable, that is, the actual data type passed in when using the template.void Swap(T &x, T &y)
: Define a template functionSwap
, the parameter isT
the type referencex
andy
, the function of the function is to exchangex
they
value of the sum.T tmp = x;
: Define a variable of typeT
andtmp
assignx
the value of to it.x = y;
:y
Assign the value ofx
.y = tmp;
:tmp
Assign the value ofy
.class myDate
: defines a date classmyDate
.myDate()
: is the default constructor, which initializes the year, month, and day to January 1, 1970. Member functionsmyDate()
are used to assign initial values to member variables, and there is no need to write the return type, because there is no need to return any value when calling the function.myDate(int y, int m, int d)
: It is a constructor function with parameters, which is used to initialize the value of year, month and day. During initialization, three integer values of year, month, and day need to be passed in, and the member variables are initialized according to the values.void printDate() const
: It is a function to print date information. The member functionprintDate()
is used to output the value of the three data in the date class, and will not modify the member variables, so addconst
modifiers to prevent member variables from being modified in the function.int main()
: It is the main function, and it is the execution starting point of the program.int n = 1, m = 2;
: Define two integer variablesn
andm
, and assign them to1
and respectively2
.Swap(n, m);
: Call the Swap function to exchange the sumn
andm
value.cout << n << " " << m << endl;
: output the exchangedn
summ
.double f = 1.2, g = 2.3;
: Define two double-precision floating-point variablesf
andg
, and assign them to1.2
and respectively2.3
.Swap(f, g);
: Call the Swap function to exchange the sumf
andg
value.cout << f << " " << g << endl;
: output the exchangedf
sumg
.myDate d1, d2(2000, 1, 1);
: Define two date objects, whichd1
are created through the default constructor andd2
created with the parameter constructor.Swap(d1, d2);
: Call the Swap function to exchange the sumd1
andd2
value.d1.printDate();
: The outputd1
date information.d2.printDate();
: The outputd2
date information.return 0;
: The program executes successfully and returns0
.【Results of the】
- First, two integer variables n and m are defined in the main function, and assigned as 1 and 2, then Swap(n, m) is called to exchange values, and the exchanged result is output, namely "1 2" becomes "2 1".
- Next, two double-precision floating-point variables f and g are defined and assigned values of 1.2 and 2.3. Swap(f, g) is called to exchange values, and the exchanged result is output, that is, "1.2 2.3" becomes "2.3 1.2".
- Finally, two date objects d1 and d2 are defined, d1 is created using the default constructor, d2 is created using the parameter constructor, and then Swap(d1, d2) is called to exchange values, that is, the year, The month and day are interchanged. Finally, the exchanged date information is output respectively, that is, "1970/1/1" and "2000/1/1" are output.
- The execution result of this program is:
1 2 2.3 1.2 1970/1/1 2000/1/1
[Example 5] Function templates can also have multiple type parameters
[Example code] The following function template is legal:
template <class T1, class T2> // 声明模板,T1和T2是类型参数 void print(T1 arg1, T2 arg2) // 定义打印函数,参数类型为T1和T2 { cout << arg1 << "," << arg2 << endl; // 打印参数arg1和arg2 }
【Code Explanation】
A printing function is defined here, and its parameter type and number are uncertain, determined by the template type parameters T1 and T2. Since T1 or T2 can be any type (including built-in types and user-defined types), this function is very convenient when printing different types of data.
When compiling, the compiler will automatically instantiate and generate a specific type of function code according to the parameter type passed when the function is called. And through the explicit instantiation of the template, the compilation time can be reduced and the code can be optimized.
The implementation of this function is relatively simple, directly output the parameters arg1 and arg2 to the screen, and wrap after each output. It should be noted that cout is a standard output stream object, which needs to include the <iostream> header file, otherwise compilation errors will occur.
(3) Matching order of function or function template call statement
Functions and function templates are also allowed to be overloaded.
C++ compilers follow the following order of precedence:
- First find an ordinary function whose parameters completely match (not a template function obtained by instantiating a template).
- Then find a template function whose parameters completely match.
- Then find an ordinary function that can match the actual parameter after automatic type conversion.
- If none of the above are found, an error will be reported.
Two, class template
(1) Class template concept
- Through class templates, classes can be instantiated one by one.
- The inheritance mechanism also establishes a certain connection between a series of classes, and these two mechanisms involving multiple classes are very different.
- A class is an abstraction of the same type of things, and classes with inheritance relationships can have different operations.
- The template is that different types of things have the same operation, and there is no connection between the instantiated classes and they are independent of each other.
[Format 1] The general format of a declaration class template is as follows:
template <模板参数表> class 类模板名 { 类体定义 }
【illustrate】
- Among them, the form of the "template parameter list" is exactly the same as the "template parameter list" in the function template.
- The definition of a class body is almost the same as that of a normal class, except that the type parameters of the template are usually used in its member variables and member functions.
【Format 2】
- A member function of a class template can be declared either within the class body or outside the class.
- If defined within a class body, it automatically becomes an inline function. If you need to define its member functions outside the class template, you should use the following format:
template <模板参数表> 返回类型名 类模板名<模板参数标识符列表>::成员函数名(参数表) { 函数体 }
【illustrate】
A class template declaration is not itself a class, it declares a family of classes. Only when referenced by other code, the template generates specific classes according to the needs of the reference
[Format 3]
- Class templates cannot be used to directly generate objects, because the type parameters are uncertain, and the "actual parameters" must be specified for the template parameters first, that is, the template can only be created after it is "instantiated".
- That is to say, when using a class template to create an object, the specific actual parameters corresponding to the type parameters or ordinary parameters should be given along with the class template name, the format is as follows:
类模板名 <模板参数表> 对象名1,…,对象名n; // 或是 类模板名 <模板参数表> 对象名1(构造函数实参),…,对象名构造函数实参);
- The process by which the compiler generates a class from a class template is called instantiation of the class template.
- A class instantiated from a class template is called a template class.
- Note that the actual parameter corresponding to the type parameter is the type name.
(2) Class template example
- Two-tuple is a commonly used structure.
- Two-tuples of two values can be defined, such as a two-tuple composed of horizontal and vertical coordinates of a point in a plane coordinate system.
- You can also define a pair of two strings, such as a pair of words and definitions in a dictionary.
- It is also possible to define a 2-tuple of student names and their grades. The examples of binary groups are too numerous to enumerate.
- If you want to define a class for dyads, you need to define many different classes depending on the types that make up the dyads.
- Now class templates can be used to solve the problem.
[Example 1] Implemented the definition and instantiation of the template class TestClass
【Example code】 Create two objects, TestClass<char> and TestClass<double> in turn in the main function, and demonstrate how to use their member variables and member functions:
#include <iostream> //包含标准输入输出流库 using namespace std; template<class T> //定义一个模板类,其数据成员为T类型数组 class TestClass { public: T buffer[10]; //T类型数组 T getData(int j); //成员函数声明,用于获取该数组中的元素 }; template<class T> //定义模板类的成员函数,返回指定下标处的数据 T TestClass<T>::getData(int j) { return *(buffer+j); }; int main() //主函数 { TestClass<char> ClassInstA; //定义一个模板类的对象,类型是char int i; char cArr[6] = "abcde"; //定义一个char类型的数据数组 for (i = 0; i < 5; i++) //赋值给buffer数组 ClassInstA.buffer[i] = cArr[i]; for (i = 0; i < 5; i++) //依次输出buffer中元素的值 { char res = ClassInstA.getData(i); //调用成员函数getData cout << res << " "; //打印结果 } cout << endl; //换行 TestClass<double> ClassInstF; //定义一个模板类的对象,类型是double double fArr[6] = {12.1, 23.2, 34.3, 45.4, 56.5, 67.6}; //定义一个double类型的数据数组 for (i = 0; i < 6; i++) //赋值给buffer数组 ClassInstF.buffer[i] = fArr[i] - 10; for (i = 0; i < 6; i++) //依次输出buffer中元素的值 { double res = ClassInstF.getData(i); //调用成员函数getData cout << res << " "; //打印结果 } cout << endl; //换行 return 0; //程序执行成功,返回0 }
【Code Explanation】
- A template class TestClass is defined, which contains an array buffer of T type and a member function getData, which is used to obtain the element at the specified position in the array buffer:
#include<iostream> //包含标准输入输出流库 using namespace std; template<class T> //定义一个模板类,其数据成员为T类型数组 class TestClass { public: T buffer[10]; //T类型数组 T getData(int j); //成员函数声明,用于获取该数组中的元素 };
- Define the function getData outside the class, and use the scope resolver "::" to indicate that this function belongs to the scope of the TestClass class. Get the element value at the specified subscript in the array buffer:
template<class T> //定义模板类的成员函数,返回指定下标处的数据 T TestClass<T>::getData(int j) { return *(buffer+j); };
- In the main function, first define a TestClass object ClassInstA, the type is specified as char. Then assign the elements in the array cArr to the buffer array of ClassInstA one by one, and then call the member function getData in turn to obtain the value of each element in the buffer, and print it out. After executing this piece of code, the output result is: "abcde" (separated by spaces), and finally a newline:
int main() { TestClass<char> ClassInstA; //定义一个模板类的对象,类型是char int i; char cArr[6] = "abcde"; //定义一个char类型的数据数组 for (i = 0; i < 5; i++) //赋值给buffer数组 ClassInstA.buffer[i] = cArr[i]; for (i = 0; i < 5; i++) //依次输出buffer中元素的值 { char res = ClassInstA.getData(i); //调用成员函数getData cout << res << " "; //打印结果 } cout << endl; //换行
- Next, define a TestClass object ClassInstF, the type is specified as double. Then subtract 10 from the elements in the array fArr and store them in the buffer array of ClassInstF one by one, and call the member function getData one by one to obtain the value of each element in the buffer, and print it out. After executing this piece of code, the output result is: "2.1 13.2 24.3 35.4 46.5 57.6" (separated by spaces), and finally a new line:
TestClass<double> ClassInstF; //定义一个模板类的对象,类型是double double fArr[6] = {12.1, 23.2, 34.3, 45.4, 56.5, 67.6}; //定义一个double类型的数据数组 for (i = 0; i < 6; i++) //赋值给buffer数组 ClassInstF.buffer[i] = fArr[i] - 10; for (i = 0; i < 6; i++) //依次输出buffer中元素的值 { double res = ClassInstF.getData(i); //调用成员函数getData cout << res << " "; //打印结果 } cout << endl; //换行
- Finally, return 0 in the main function, and the program execution ends:
return 0; //程序执行成功,返回0 }
【Results of the】
- The program defines a template class TestClass, which has a data member buffer, which is an array of type T. TestClass also has a member function getData, which is used to obtain the value at the specified subscript in the buffer.
- In the main function, an object ClassInstA of type TestClass<char> is first created, and the string "abcde" is stored in the buffer array of ClassInstA one by one, and then the values of the elements in the buffer are obtained one by one and printed out. Therefore, each character of "abcde" (separated by spaces) is printed first in the execution result, and then a new line is printed.
- Next, create an object ClassInstF of type TestClass<double>, and subtract 10 from each element in the array of {12.1, 23.2, 34.3, 45.4, 56.5, 67.6}, and store it in the buffer array. Then obtain the values of the elements in the buffer in turn, and print them out. Therefore, the execution result first prints the value of each element minus 10 (separated by spaces), and then wraps.
- It should be noted that T can be any data type. By specifying different types of type parameters T, different class objects can be created and operated on. In addition, because it is a template class, you can reuse this class template in the program to create many objects, instead of writing a new class for each requirement.
- The program execution result is:
a b c d e 2.1 13.2 24.3 35.4 46.5 57.6
[Example 2] The use of class templates and arrays
[Sample code] shows the use of class templates and arrays in C++, and how to access the elements in the array through the subscript of the array, and output its value:
#include <iostream> using namespace std; template<int i> class TestClass { public: int buffer[i]; // 声明一个大小固定为 i 的整型数组 int getData(int j); // 声明一个获取 buffer 下标为 j 的元素值的方法 }; template<int i> int TestClass<i>::getData(int j) { return *(buffer+j); // 返回 buffer 数组下标为 j 的元素值 } int main() { TestClass<6> ClassInstF; // 初始化大小为 6 的 TestClass 实例 int i; double fArr[6] = {12.1, 23.2, 34.3, 45.4, 56.5, 67.6}; for (i = 0; i < 6; i++) { ClassInstF.buffer[i] = fArr[i] - 10; // 循环将 fArr 中每个元素减去 10 后赋值给 ClassInstF 的 buffer 数组 } for (i = 0; i < 6; i++) { double res = ClassInstF.getData(i); // 循环获取 ClassInstF 的 buffer 数组中每个元素的值 cout << res << " "; } cout << endl; return 0; }
【Code Explanation】
- The program defines a
TestClass
class template named , which contains ani
array of integers of size and a method to get the elements of the array. Then inmain
the function, first declare aTestClass
type object with a size of 6ClassInstF
, then use a loop to subtract 10 from each element infor
a known double-precision array and assign it to the array, and finally use the array accessed by the loop , and Output the value of each element in it. This program can help understand how to use class templates and arrays in C++.fArr
ClassInstF
buffer
for
ClassInstF
buffer
- Header declarations and namespaces:
#include <iostream> using namespace std;
- Define a class template named TestClass, the template parameter is i, where buffer is an array of int type with size i, getData is a public method, the parameter is j of type int, and the return value is the element with subscript j in the buffer array value:
template<int i> class TestClass { public: int buffer[i]; // 声明一个大小固定为 i 的整型数组 int getData(int j); // 声明一个获取 buffer 下标为 j 的元素值的方法 };
- Define the specific implementation of the getData method in the TestClass class, perform subscript access to the buffer array according to the parameter j passed in, and return the obtained element value:
template<int i> int TestClass<i>::getData(int j) { return *(buffer+j); // 返回 buffer 数组下标为 j 的元素值 }
- In the main function, declare an instance of ClassInstF of type TestClass<6>, where the value of i is 6. Through the for loop, subtract 10 from the value of each element in the fArr array with a size of 6 and store it in the buffer array of ClassInstF. Through the for loop again, store the value of each element in the buffer array of ClassInstF into res, and then output the value. Finally, output a newline and return 0:
int main() { TestClass<6> ClassInstF; // 初始化大小为 6 的 TestClass 实例 int i; double fArr[6] = {12.1, 23.2, 34.3, 45.4, 56.5, 67.6}; for (i = 0; i < 6; i++) { ClassInstF.buffer[i] = fArr[i] - 10; // 循环将 fArr 中每个元素减去 10 后赋值给 ClassInstF 的 buffer 数组 } for (i = 0; i < 6; i++) { double res = ClassInstF.getData(i); // 循环获取 ClassInstF 的 buffer 数组中每个元素的值 cout << res << " "; } cout << endl; return 0; }
【Results of the】
- The result is to
fArr
subtract 10 from each element in and store inClassInstF
thebuffer
array, and then outputbuffer
the value of each element in the array in turn. Sincebuffer
the element type of the array is an integer, andfArr
the element type of is a double-precision floating-point number,fArr
each element of is also converted to an integer when it is subtracted by 10.2.1 13.2 24.3 35.4 46.5 57.6
(3) Class templates and inheritance
Inheritance is allowed between classes and between class templates.Specifically, class templates and class templates, class templates and classes can inherit each other, and the common derivation relationship between them has the following four situations:
- Ordinary classes inherit template classes.
- Class templates inherit from ordinary classes.
- Class templates inherit class templates.
- Class templates inherit template classes.
A class instantiated from a class template is a template class.
[Example 1] How to use class templates and the definition and inheritance methods of derived classes
【Example code】
- The following program defines a class template base class
TBase
and aTBase
class derived fromDerived
, using the data membersdata
and member functions in the class templatedata
the values of the data members.- In
main
the function, the program first createsDerived
an object of the classd
andDerived
inherits itTBase<int>
, andTBase
the data type in the template class isT
similar to a generic type, sodata
the data type isint
. Then,d
the member function called by the programprint()
outputsdata
the value of the data member to the standard output stream, that is, to the screen.- The following program is mainly to demonstrate the use of class templates and the definition and inherited methods of derived classes:
#include <iostream> using namespace std; template <class T> // 定义类模板基类 class TBase { T data; // 类模板基类中的数据成员 public: void print() { // 在类模板基类中定义成员函数 cout << data << endl; } }; class Derived : public TBase<int> { // 使用类模板基类,定义普通派生类 }; int main() { Derived d; // 定义普通派生类对象 d.print(); // 调用类模板基类中的成员函数 return 0; }
【Code Explanation】
- The program defines
TBase
a base class named class template that contains a data memberdata
and a member functiondata
value.Derived
Next, a generic derived class named is defined , whichTBase
inherits from the template base class. The object of a classmain
is defined in the function , and then the member function output in the base class is called . Since it is a class template, it is necessary to specify the type of the template parameter when using it, which is used here .Derived
d
print()
data
TBase
int
- Include header files and namespace declarations:
#include <iostream> using namespace std;
- Define
TBase
a class template named, which contains a data memberdata
and a member functiondata
:template <class T> // 定义类模板基类 class TBase { T data; // 类模板基类中的数据成员 public: void print() { // 在类模板基类中定义成员函数 cout << data << endl; } };
- Define an ordinary derived class
Derived
that inherits fromTBase<int>
:class Derived : public TBase<int> { // 使用类模板基类,定义普通派生类 };
- In
main
the function, first declare ad
derived class object namedDerived
. Then, calld
the member functiondata
the value. SinceDerived
it is derived fromTBase<int>
, the typeTBase
in the class templatedata
isint
, which can be output directly. Finally return value 0:int main() { Derived d; // 定义普通派生类对象 d.print(); // 调用类模板基类中的成员函数 return 0; }
【Results of the】
Because
TBase
the data member in the template classdata
is not initialized, its value will depend on the old data stored at that memory location. In this program,data
is of typeint
, so the default initial value is 0.In the function, a class object named is defined, and then the member function inherited from is called ,
main
and the output is the initial value 0 in the template class .d
Derived
d
TBase<int>
TBase
data
Therefore, the program outputs an integer value of 0:
0
[Example 2] Inheritance of classes and explicit call methods of member functions
【Example code】
#include <iostream> #include <string> using namespace std; class TBase { // 定义类 TBase int k; // 私有数据成员 k public: void print() { // 公有成员函数 print 输出 k 的值 cout << "TBase::" << k << endl; } }; template <class T> class TDerived : public TBase { // 定义类 TDerived 继承自 TBase T data; // 私有数据成员 data public: void setData(T x) { // 设置 data 值 data = x; } void print() { // 输出 data 和 k 的值 TBase::print(); // 调用基类中的 print 函数 cout << "TDerived::" << data << endl; } }; int main() { TDerived<string> d; // 定义 TDerived 类对象 d d.setData("2019"); // 设置 d 的 data 值为 "2019" d.print(); // 输出 data 和 k 的值 return 0; }
【Code Explanation】
The program is mainly to demonstrate the inheritance of classes and the explicit call method of member functions, as well as the use of class templates. Among them, both the base class
TBase
and the derived classTDerived
containTBase::print()
explicitly calledk
.- Include header files and namespace declarations:
#include <iostream> #include <string> using namespace std;
- A class named named is defined
TBase
, which contains a private data memberk
and a public member functionk
value of the function is:class TBase { // 定义类 TBase int k; // 私有数据成员 k public: void print() { // 公有成员函数 print 输出 k 的值 cout << "TBase::" << k << endl; } };
- Defines a class template
TDerived
, which the class inherits fromTBase
, that contains a private data memberdata
and two member functionssetData
andsetData
the function is used to setdata
the value, anddata
and inherit the value from the baseTBase
classk
. It should be noted that inTBase::print()
to the function in the base class is used:template <class T> class TDerived : public TBase { // 定义类 TDerived 继承自 TBase T data; // 私有数据成员 data public: void setData(T x) { // 设置 data 值 data = x; } void print() { // 输出 data 和 k 的值 TBase::print(); // 调用基类中的 print 函数 cout << "TDerived::" << data << endl; } };
- In the function, a class object named
main
is first defined , and then the function that calls it sets the value of the value to the string "2019". Finally, the called function outputs and inherits the value from the base class :d
TDerived<string>
setData
data
d
data
TBase
k
int main() { TDerived<string> d; // 定义 TDerived 类对象 d d.setData("2019"); // 设置 d 的 data 值为 "2019" d.print(); // 输出 data 和 k 的值 return 0; }
【Results of the】
- The program defines a base class and a template class inherited
TBase
from , where the class contains a private data member , and the class contains a private data member , and also contains two member functions and . In the function, call the function of the base class to print out the value, and output the value to the standard output stream, that is, output to the screen.TBase
TDerived
TBase
k
TDerived
data
setData
TBase
k
data
- In the function, a class object named
main
is first defined , and then the function that calls it sets the value of the value to the string "2019". Finally, the called function outputs and inherits the value from the base class .d
TDerived<string>
setData
data
d
data
TBase
k
- Since the data members
TBase
in the classk
are not explicitly initialized, whenTDerived
the class object is instantiated, its data membersk
get a default value of 0. Therefore, the output of the program is "TBase::0\nTDerived::2019".TBase::0 TDerived::2019
[Example 3] Definition, inheritance and call of member functions of class template
[Example code] The role of the member function functions
#include <iostream> #include <string> using namespace std; template <class T> class TBase { // 定义类模板 TBase T data1; // 私有数据成员 data1 public: void print() { // 成员函数 print 输出 data1 的值 cout << "TBase::" << data1 << endl; } }; template <class T1, class T2> class TDerived : public TBase<T1> { // 定义类模板 TDerived,继承 TBase T2 data2; // 私有数据成员 data2 public: void print() { // 成员函数 print 输出 data1 和 data2 的值 TBase<T1>::print(); // 调用基类 TBase 的 print 函数 cout << "TDerived::" << data2 << endl; } }; int main() { TDerived<int, int> d; // 声明 TDerived<int, int> 类对象 d d.print(); // 输出 data1 和 data2 的值 TDerived<string, string> d2; // 声明 TDerived<string, string> 类对象 d2 d2.print(); // 输出 data1 和 data2 的值 return 0; }
【Code Explanation】
- This program is mainly to demonstrate the definition of class template, inheritance and call of its member functions. The role of the member function is to output the value of the data member in the class to the standard output stream, and the program calls their functions
TDerived
TBase
data1
TDerived
data2
- Header declarations and namespaces:
#include <iostream> #include <string> using namespace std;
- defines a
TBase
class template named , which contains a private data member anddata1
a public member function for the output value:data1
#include <iostream> #include <string> using namespace std; template <class T> class TBase { // 定义类模板 TBase T data1; // 私有数据成员 data1 public: void print() { // 成员函数 print 输出 data1 的值 cout << "TBase::" << data1 << endl; } };
- Defines a
TDerived
class template named, inherited fromTBase
, and contains a private data memberdata2
and a public member functionTBase<T1>::print()
makes an explicit call to the base class to output the valueTBase
in the base classdata1
, and thendata2
output the value of to the standard output stream:template <class T1, class T2> class TDerived : public TBase<T1> { // 定义类模板 TDerived,继承 TBase T2 data2; // 私有数据成员 data2 public: void print() { // 成员函数 print 输出 data1 和 data2 的值 TBase<T1>::print(); // 调用基类 TBase 的 print 函数 cout << "TDerived::" << data2 << endl; } };
- In the function, a class object
main
is declared first , and its function is called to output the value of the data member. Then declare a class object and call its function to output the value of the data member:TDerived<int, int>
d
TDerived<string, string>
d2
int main() { TDerived<int, int> d; // 声明 TDerived<int, int> 类对象 d d.print(); // 输出 data1 和 data2 的值 TDerived<string, string> d2; // 声明 TDerived<string, string> 类对象 d2 d2.print(); // 输出 data1 和 data2 的值 return 0; }
【Results of the】
- The program defines a class template and a class template
TBase
inherited from , wherein the class contains a private data member and a public member function , and the class contains a private data member and a public member function . In the function, the function in the base class is called , and the value of the data member in the class is output to the standard output stream.TBase
TDerived
TBase
data1
TDerived
data2
TBase<T1>::print()
TBase
- In the function, a class object named
main
is first defined , and its function is called to output the value of the data member. Next, a class object named is defined , and its function is called to output the value of the data member.d
TDerived<int, int>
d2
TDerived<string, string>
- In this program, because the base class
TBase
and the derived classTDerived
define different template parameter types, theTDerived
default constructor will be used when instantiating the class object (that is, the data member is initialized to 0 or an empty string by default when no value is provided ( "").). So, the output is "TBase::0\nTDerived::0\nTBase::\nTDerived::\n".TBase::0 TDerived::0 TBase:: TDerived::
[Example 4] Definition and use of class templates
[Example code] This program defines two class templates
TBase
andTDerived
:
TBase
The template defines a public data memberdata1
and a member functiondata1
the value of the data memberTDerived
A template inherits from aTBase
template and defines a public data memberdata2
and a member functionTBase<T1>::print()
#include <iostream> #include <string> using namespace std; template <class T> class TBase { public: T data1; // 公有数据成员 data1 public: void print() { cout << "TBase::" << data1 << endl; // 成员函数 print 输出 data1 的值 } }; template <class T1, class T2> class TDerived : public TBase<T1> { public: T2 data2; // 公有数据成员 data2 public: void print() { TBase<T1>::print(); // 成员函数 print 调用基类 TBase 的 print 函数输出 data1 的值 cout << "TDerived::" << data2 << endl; // 输出 data2 的值 } }; int main() { TDerived<int, int> d; // 声明 TDerived<int, int> 类对象 d d.data1 = 5; // 给 d 的 data1 赋值 5 d.data2 = 8; // 给 d 的 data2 赋值 8 d.print(); // 输出 data1 和 data2 的值 TDerived<string, string> d2; // 声明 TDerived<string, string> 类对象 d2 d2.data1 = "happy"; // 给 d2 的 data1 赋值 "happy" d2.data2 = "new year"; // 给 d2 的 data2 赋值 "new year" d2.print(); // 输出 data1 和 data2 的值 TDerived<int, string> d1; // 声明 TDerived<int, string> 类对象 d1 d1.data1 = 2020; // 给 d1 的 data1 赋值 2020 d1.data2 = "good luck"; // 给 d1 的 data2 赋值 "good luck" d1.print(); // 输出 data1 和 data2 的值 return 0; }
【Code Explanation】
- This code defines a template class
TBase
and aTBase
template class inherited from classTDerived
, andmain
declares and uses instances of these two classes in the function.- Header declarations and namespaces:
#include <iostream> #include <string> using namespace std;
- This part of the code defines a template class
TBase
in which member variablesdata1
are public and member functionsdata1
values.TBase
An object of typedata1
isT
an object of the template type:template <class T> class TBase { public: T data1; // 公有数据成员 data1 public: void print() { cout << "TBase::" << data1 << endl; // 成员函数 print 输出 data1 的值 } };
- This part of the code defines a
TBase
template class that inherits from the template classTDerived
, whereT1
andT2
are two different template parameters.TDerived
Objects of typedata2
and are objects of type anddata1
respectively . The value output by the member function , which first calls the value output by the function of the base class , and then outputs the value:T2
T1
data1
TBase
data1
data2
template <class T1, class T2> class TDerived : public TBase<T1> { public: T2 data2; // 公有数据成员 data2 public: void print() { TBase<T1>::print(); // 成员函数 print 调用基类 TBase 的 print 函数输出 data1 的值 cout << "TDerived::" << data2 << endl; // 输出 data2 的值 } };
- This part of the code defines
main
the function. In the function,TDerived
objects of three template classesd
,d2
and and are declared respectivelyd1
, using different template parameter types. After assigning values to the member variables of the objectdata1
anddata2
respectively,TDerived
The function is called once for each objectint main() { TDerived<int, int> d; // 声明 TDerived<int, int> 类对象 d d.data1 = 5; // 给 d 的 data1 赋值 5 d.data2 = 8; // 给 d 的 data2 赋值 8 d.print(); // 输出 data1 和 data2 的值 TDerived<string, string> d2; // 声明 TDerived<string, string> 类对象 d2 d2.data1 = "happy"; // 给 d2 的 data1 赋值 "happy" d2.data2 = "new year"; // 给 d2 的 data2 赋值 "new year" d2.print(); // 输出 data1 和 data2 的值 TDerived<int, string> d1; // 声明 TDerived<int, string> 类对象 d1 d1.data1 = 2020; // 给 d1 的 data1 赋值 2020 d1.data2 = "good luck"; // 给 d1 的 data2 赋值 "good luck" d1.print(); // 输出 data1 和 data2 的值 return 0; }
【Results of the】
- This result is due to the program defining template classes
TBase
andTDerived
. A subclass of Yes, each class has aTDerived
variable named and of type and respectively . The function creates three objects of the class and assigns values to their data members. Then by calling the function of each object , the sum of each object is output .TBase
data1
data2
T1
T2
main
TDerived
print()
data1
data2
TBase::5 TDerived::8 TBase::happy TDerived::new year TBase::2020 TDerived::good luck
[Example 5] Definition of class template
[Example code] This program defines two class templates, which are
TBase
andTDerived:
TBase
data1
Private member variables and member functions are defined in the class templateprint()
, and their access rights areprivate
andpublic
TDerived
Class templates inherit fromTBase<int>
templates and define private member variablesdata2
and public member functionsprint()
#include <iostream> #include <string> using namespace std; template<class T> class TBase // 类模板 { T data1; public: void print() { cout << "TBase::" << data1 << endl; } }; template<class T2> class TDerived: public TBase<int> // 类模板继承于模板类 { T2 data2; public: void print() { TBase<int>::print(); // 调用基类 TBase 的 print 函数输出 data1 的值 cout << "TDerived::" << data2 << endl; } }; int main() { TDerived<int> d; d.print(); TDerived<string> d2; d2.print(); return 0; }
【Code Explanation】
The program defines two class templates, namely
TBase
andTDerived
. Private member variables and member functionsTBase
are defined in the class template , and their access permissions are and . Class templates inherit from templates and define private member variables and public member functions .data1
print()
private
public
TDerived
TBase<int>
data2
print()
In
main
the function, the program declares the objects of the two template classesTDerived<int>
and respectively , and calls their functions. In the output result, the previous string sum is output in the function, and the subsequent value or string is the member variable value of the object .TDerived<string>
d
d2
print()
"TBase::"
"TDerived::"
print()
- Header declarations and namespaces:
#include <iostream> using namespace std;
- This part of the code defines a
TBase
class template with a private member variabledata1
and a public member functionprint()
for the outputdata1
value:template<class T> class TBase // 类模板 { T data1; public: void print() { cout << "TBase::" << data1 << endl; } };
- This part of the code defines a
TDerived
class template that inherits fromTBase<int>
the template and has aT2
public member variable of typedata2
. The member functionprint()
outputsdata1
the value of anddata2
the value of where the method of::
the base class is invoked by using a double colon between the base class name and the function name :TBase
print()
template<class T2> class TDerived: public TBase<int> // 类模板继承于模板类 { T2 data2; public: void print() { TBase<int>::print(); // 调用基类 TBase 的 print 函数输出 data1 的值 cout << "TDerived::" << data2 << endl; } };
- This part of the code
main()
usesTDerived
the class template in the function to instantiate two objectsd
andd2
, respectivelyTDerived<int>
andTDerived<string>
. Next, the program calls methods on each object , outputting the values of andprint()
respectively :data1
data2
int main() { TDerived<int> d; d.print(); TDerived<string> d2; d2.print(); return 0; }
【Results of the】
The program uses the class template
TBase
andTDerived
andmain
creates the objectTDerived<int>
and of and in the function . Because the class inherits from , T is specified in , and in , T is specified as the default .TDerived<string>
d
d2
TDerived
TBase<int>
TDerived<int>
int
TDerived<string>
string
The program first calls the function
d
of the object , the member functionprint()
called by the function , outputs "TBase::0", and then outputs the value "", this is because the class template is uninitialized, so its value is the default value. Next, the program calls the function of the object again , and the same function is called , and outputs "TBase::", and then outputs the value "".TBase<int>
print()
data2
TDerived<int>
data2
d2
print()
TBase<int>
print()
data2
Therefore, the output of the program is:
TBase::0 TDerived:: TBase:: TDerived::
[Example 6] How to use class templates and inheritance and how to use them together
[Example code] The inheritance relationship between classes is established through two template classes. Code reuse can be easily realized through inheritance. At the same time, the use of class templates makes the code applicable to different data types:
#include <iostream> #include <string> using namespace std; template<class T> class TBase // 定义类模板 TBase { public: T data1; // 一个公有成员变量 void print() // 一个公有成员函数,输出 data1 的值 { cout << "TBase::" << data1 << endl; } }; template<class T2> class TDerived: public TBase<int> // 定义类模板 TDerived,它继承于模板类 TBase<int> { public: T2 data2; // 一个公有成员变量 void print() // 一个公有成员函数,输出 data1 的值及 data2 的值 { TBase<int>::print(); // 调用基类 TBase 的 print 函数输出 data1 的值 cout << "TDerived::" << data2 << endl; } }; int main() { TDerived<int> d; // 声明一个 TDerived<int> 对象 d d.data1 = 5; // 初始化对象 d 的 data1 成员 d.data2 = 8; // 初始化对象 d 的 data2 成员 d.print(); // 调用对象 d 的 print 成员函数,输出结果 TDerived<string> d2; // 声明一个 TDerived<string> 对象 d2 d2.data1 = 2020; // 初始化对象 d2 的 data1 成员 d2.data2 = "good luck"; // 初始化对象 d2 的 data2 成员 d2.print(); // 调用对象 d2 的 print 成员函数,输出结果 return 0; // 返回 0,表示程序运行正常结束 }
【Code Explanation】
The program uses the class template
TBase
andTDerived
andmain
creates the objectTDerived<int>
and of and in the function . Among them, the class template is a simple class, including a member variable and a member function; the class template is a class template inherited from the template, adding a member variable and a member function.TDerived<string>
d
d2
TBase
data1
print()
TDerived
TBase<int>
data2
print()
In
main()
the function, the program first declares anTDerived<int>
object , initializesd
itdata1
and its members, and calls its function to output the result. Then declare an object , initialize it and its members, and call its function to output the result.data2
print()
TDerived<string>
d2
data1
data2
print()
- Header declarations and namespaces:
#include <iostream> #include <string> using namespace std;
- A class template TBase is defined, which contains a public member data1 and a public member function print() to output the value of data1:
template<class T> class TBase // 定义类模板 TBase { public: T data1; // 一个公有成员变量 void print() // 一个公有成员函数,输出 data1 的值 { cout << "TBase::" << data1 << endl; } };
- The class template TDerived is defined, which is inherited from the template class TBase<int>. A public member data2 and a public member function print() are defined to output the values of data1 and data2. In the print() function, in order to call the print() function of the base class TBase to output the value of data1, the TBase<int>::print() syntax is used:
template<class T2> class TDerived: public TBase<int> // 定义类模板 TDerived,它继承于模板类 TBase<int> { public: T2 data2; // 一个公有成员变量 void print() // 一个公有成员函数,输出 data1 的值及 data2 的值 { TBase<int>::print(); // 调用基类 TBase 的 print 函数输出 data1 的值 cout << "TDerived::" << data2 << endl; } };
- In the main function, a TDerived<int> object d is declared first, then the data1 and data2 members of d are initialized, and finally the print() function of d is called. Then declare a TDerived<string> object d2, and then initialize the data1 and data2 members of d2 respectively, and finally call the print() function of d2. Finally, 0 is returned, indicating that the program execution has ended successfully:
int main() { TDerived<int> d; // 声明一个TDerived<int>对象d d.data1 = 5; // 初始化对象d的data1成员 d.data2 = 8; // 初始化对象d的data2成员 d.print(); // 调用对象d的print成员函数,输出结果 TDerived<string> d2; // 声明一个TDerived<string>对象d2 d2.data1 = 2020; // 初始化对象d2的data1成员 d2.data2 = "good luck"; // 初始化对象d2的data2成员 d2.print(); // 调用对象d2的print成员函数,输出结果 return 0; // 返回0,表示程序运行正常结束 }
【Results of the】
The data1 member of object d is initialized to 5, and the data2 member is initialized to 8. Calling the print() function of object d first outputs "TBass::5" and then "TDerived::8".
The data1 member of object d2 is initialized to 2020, and the data2 member is initialized to "good luck". Call the print() function of the object d2, first output "TBase::2020", and then output "TDerived::good luck".
TBase::5 TDerived::8 TBase::2020 TDerived::good luck