[C++ Programming] Chapter 9: Function Templates and Class Templates

Table of contents

1. Function template

(1) The concept of function template

(2) Example of a function template 

(3) Matching order of function or function template call statement 

Two, class template

(1) Class template concept 

(2) Class template example 

(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 absto obtain the absolute value of any type of variable through the template parameter T. Different types of variables are defined in the main function, and abs 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 as std::cout and  std::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 type  T variable x.
  • In the main function, we initialize four variables  n, m, d and  f, which are integer  -5, integer,  10double-precision floating-point  -0.5 and single-precision floating-point  3.2. Next, we call  abs the function separately to output the absolute value of each variable. Finally, the program executes successfully and returns  0.

【Results of the】

  • This code creates a template function  absto obtain the absolute value of any type of variable through the template parameter T. Different types of variables are defined in the main function, and  abs 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 in  xand its corresponding absolute value is returned. Use the ternary operator to judge, if it is  x less than 0, take the opposite number, otherwise return directly  x.

[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 in  x, and its corresponding absolute value is returned. Use the ternary operator to judge, if it is  x less than 0, take the opposite number, otherwise return directly  x.
  • In fact, a function template is not a concrete function for which the compiler cannot generate executable code. define function modulo
    Behind 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 which  Swap the variable value exchange of different types can be realized. A class is also defined  myDate 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  the  Swap 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, use  class or  typename 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 function  Swap, the parameter is  T the type reference  x and  y, the function of the function is to exchange  x the  y value of the sum.
  • T tmp = x;: Define a variable of type  T and  tmp assign  x the value of to it.
  • x = y;y Assign the value of  x.
  • y = tmp;tmp Assign the value of  y.
  • class myDate: defines a date class  myDate.
  • myDate(): is the default constructor, which initializes the year, month, and day to January 1, 1970. Member functions  myDate() 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 function  printDate() is used to output the value of the three data in the date class, and will not modify the member variables, so add  const 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 variables  n and  m, and assign them to  1 and  respectively 2.
  • Swap(n, m);: Call the Swap function to  exchange the sum n and  m value.
  • cout << n << " " << m << endl;: output the exchanged  n sum  m.
  • double f = 1.2, g = 2.3;: Define two double-precision floating-point variables  f and  g, and assign them to  1.2 and  respectively 2.3.
  • Swap(f, g);: Call the Swap function to  exchange the sum f and  g value.
  • cout << f << " " << g << endl;: output the exchanged  f sum  g.
  • myDate d1, d2(2000, 1, 1);: Define two date objects, which  d1 are created through the default constructor and d2 created with the parameter constructor.
  • Swap(d1, d2);: Call the Swap function to  exchange the sum d1 and  d2 value.
  • d1.printDate();: The output  d1 date information.
  • d2.printDate();: The output  d2 date information.
  • return 0;: The program executes successfully and returns  0.

【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:
  1. First find an ordinary function whose parameters completely match (not a template function obtained by instantiating a template).
  2. Then find a template function whose parameters completely match.
  3. Then find an ordinary function that can match the actual parameter after automatic type conversion.
  4. 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 an  i array of integers of size and a method to get the elements of the array. Then in  main the function, first declare a  TestClass type object  with a size of 6 ClassInstF, then use  a loop  to subtract 10 from each element in  for 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++.fArrClassInstFbufferforClassInstFbuffer
  • 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 in  ClassInstF the  buffer array, and then output  buffer the value of each element in the array in turn. Since  buffer the element type of the array is an integer, and  fArr 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 a  TBase class derived from  Derived, using the data members  data and member functions  in the class template print to output  data the values ​​of the data members.
  • In  main the function, the program first creates  Derived an object of the class  dand Derived inherits it  TBase<int>, and  TBase the data type in the template class is  Tsimilar to a generic type, so  data the data type is  int. Then,  d the member function called by  the program print()outputs  data 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 member  data and a member function  printfor the output  data value. Derived Next, a generic derived class named  is defined  , which TBase inherits from the template base class.  The object of a class  main 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  .Deriveddprint()dataTBaseint
  • Include header files and namespace declarations:
    #include <iostream>
    using namespace std;
  • Define  TBase a class template named, which contains a data member  data and a member function  print, the value that the function  print can output  data :
    template <class T> // 定义类模板基类
    class TBase {
        T data; // 类模板基类中的数据成员
    public:
        void print() { // 在类模板基类中定义成员函数
            cout << data << endl;
        }
    };
  • Define an ordinary derived class  Derivedthat inherits from  TBase<int>:
    class Derived : public TBase<int> { // 使用类模板基类,定义普通派生类
    };
  • In  main the function, first declare a  d derived class object named  Derived. Then, call  d the member function  printthat outputs  data the value. Since  Derived it is derived from  TBase<int>,  the type TBase in the class template  data is  int, 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 class  data is not initialized, its value will depend on the old data stored at that memory location. In this program, data is of type  int, 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   .dDeriveddTBase<int>printTBasedata

  • 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 class  TDerived contain  print functions, and in the derived class, the functions in the base class need to be  TBase::print() explicitly called  print to output the functions in the base class  k.

  • 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 member  k and a public member function  print, and the print output  k 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 from  TBase, that contains a private data member  data and two member functions  setData and  print. Among them, setData the function is used to set  data the value, and print the function is used to output  data and inherit the value from the base  TBase class  k . It should be noted that in  print the function,   an explicit call TBase::print() to the function in the base class  is used:print
    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   :dTDerived<string>setDatadatadprintdataTBasek
    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.TBaseTDerivedTBasekTDeriveddatasetDataprintprintTBaseprintkdata
  • 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   .dTDerived<string>setDatadatadprintdataTBasek
  • Since  the data members TBase in the class  k are not explicitly initialized, when  TDerived the class object is instantiated, its data members  k 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  functionsprint by instantiating different types of class templates: print

#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 print by instantiating different types of class templates  . Among them, both the base class   and   the derived class   are   output to the standard output stream.TDerivedprintTBasedata1TDeriveddata2
  • Header declarations and namespaces:
    #include <iostream>
    #include <string>
    
    using namespace std;
  • defines a  TBase class template named , which contains a private data member  and data1 a public member function   for the output   value:printprintdata1
    #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 from  TBase, and contains a private data member  data2 and a public member function  print, where  the form print used in the function  TBase<T1>::print() makes an explicit call to the base class to output   the value TBase in  the base class data1, and then  data2 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>dprintTDerived<string, string>d2print
    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.TBaseTDerivedTBasedata1printTDeriveddata2printprintTBase<T1>::print()TBaseprint
  • 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.dTDerived<int, int>printd2TDerived<string, string>print
  • In this program, because the base class  TBase and the derived class  TDerived define different template parameter types, the  TDerived 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 and TDerived:

  • TBase The template defines a public data member  data1 and a member function  print. print The function is responsible for outputting  data1 the value of the data member
  • TDerived A template inherits from a  TBase template and defines a public data member  data2 and a member function  print. print used in the function TBase<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 a  TBase template class inherited from class  TDerived, and  main 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  TBasein which member variables  data1 are public and member functions  print are used to output  data1 values. TBase An object of type  data1 is  T 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 class  TDerived, where  T1 and  T2 are two different template parameters. TDerived Objects of type  data2 and  are objects of type  and  data1 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:T2T1printdata1TBaseprintdata1data2
    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 classes d, d2 and and  are declared respectively d1, using different template parameter types. After assigning values ​​to the member variables of the object  data1 and  data2 respectively,  print the function is called to output the member variable values ​​of different types of template parameter objects. TDerived The function is called once for  each  object print :
    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;
    }

【Results of the】

  • This result is due to the program defining template classes  TBase and  TDerived.  A subclass of Yes, each class has a  TDerived 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  .TBasedata1data2T1T2mainTDerivedprint()data1data2
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 and TDerived:

  • TBasedata1 Private member variables and member functions   are defined in the class template  print(), and their access rights are  private and public
  • TDerived Class templates inherit from  TBase<int> templates and define private member variables  data2 and public member functions print()
#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 and  TDerived.  Private member variables and member functions  TBase 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  .data1print()privatepublicTDerivedTBase<int>data2print()

  • In  main the function, the program declares   the objects of  the two template classes TDerived<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>dd2print()"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 variable  data1and a public member function  print()for the output  data1 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 from  TBase<int> the template and has a  T2 public member variable  of type data2. The member function  print() outputs  data1 the value of and  data2 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  :TBaseprint()
    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() uses  TDerived the class template in the function to instantiate two objects  d and  d2, respectively  TDerived<int> and  TDerived<string>. Next, the program calls methods on each object  , outputting the values ​​of  and  print() respectively   :data1data2
    int main()
    {
        TDerived<int> d; 
        d.print();
        TDerived<string> d2;
        d2.print();
    
        return 0;
    }

【Results of the】

  • The program uses the class template  TBase and  TDerivedand  main creates   the object  TDerived<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>dd2TDerivedTBase<int>TDerived<int>intTDerived<string>string

  • The program first calls  the function d of the object  , the  member function  print() 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()data2TDerived<int>data2d2print()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 and  TDerivedand  main creates   the object  TDerived<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>dd2TBasedata1print()TDerivedTBase<int>data2print()

  • In  main() the function, the program first declares an  TDerived<int> object  ,  initializes  dit  data1 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.data2print()TDerived<string>d2data1data2print()

  •  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

Guess you like

Origin blog.csdn.net/qq_39720249/article/details/131403357