Haste makes waste

Nano01(自動運転)-【C++】-Lesson10-Templates模板

Posted on By lijun

1. Templates Example

上一章的重载一定程度达到了泛化的效果,但是还不够,通过模板可以更加简洁:

#include<iostream>

using namespace std;

//Our generic function
template <typename T>  //tell the compiler we are using a template
T findSmaller(T input1,T  input2); 

int main()
{
    int a = 54; 
    int b = 89;
    float f1 = 7.8;
    float f2 = 9.1;
    char c1 = 'f';
    char c2 = 'h';
    string s1 = "Hello";
    string s2 = "Bots are fun";
    
    //Wow! We can use one function for different variable types
    cout<<"\nIntegers compared: "<<findSmaller(a,b);
    cout<<"\nFloats compared: "<<findSmaller(f1,f2);
    cout<<"\nChars compared: "<<findSmaller(c1,c2);
    cout<<"\nStrings compared: "<<findSmaller(s1,s2);   
    return 0;
}

template <typename T>
T findSmaller(T  input1,T  input2)
{
    if(input1 < input2)
        return input1;
    else
        return input2;
}
Integers compared: 54
Floats compared: 7.8
Chars compared: f
Strings compared: Bots are fun

5. Func. Templates 2

上面的模板函数中,都是相同的数据类型,其实也可以接收不同的数据类型:

/*Goal: learn to use templates with multiple variable types. 
*/

#include<iostream>
using namespace std;

template <typename T, typename U>
T getBigger(T input1, U input2);


int main()
{
    int a = 5;
    float b = 6.334;
    int bigger;
    cout<<"Between "<<a<<" and "<<b<<" "<<getBigger(a,b)<<" is bigger.\n";

    cout<<"Between "<<a<<" and "<<b<<" "<<getBigger(b,a)<<" is bigger.\n";    
    return 0;
}

template <typename T, typename U>
T getBigger(T input1, U input2)
{
    if(input1 > input2)
        return input1;
    return input2;
}
Between 5 and 6.334 6 is bigger.
Between 5 and 6.334 6.334 is bigger.

6. Generic Classes

类似于模板函数,也可以创建泛化的类,下面的示例代码:

main.hpp:

//header file for main.cpp

#include<iostream>

//The class accepts strings, 
//so we need to use namespace
using namespace std;

//tell compiler this class uses a generic value
template <class T>
class StudentRecord
{
    private:
        const int size = 5;
        T grade;
        int studentId;
    public:
        StudentRecord(T input);
        void setId(int idIn);
        void printGrades();
};

template<class T>
StudentRecord<T>::StudentRecord(T input)
{
    grade=input;
}

template<class T>
void StudentRecord<T>::setId(int idIn)
{
    studentId = idIn;
}

template<class T>
void StudentRecord<T>::printGrades()
{
    cout<<"ID# "<<studentId<<": ";
    cout<<grade<<"\n ";
    cout<<"\n";
}

main.cpp:

/*Goal: examine generic classes.
*/

/*Goal: study generic classes*/

#include "main.hpp"

int main()
{
    //StudentRecord is the generic class
    //The constructor sets the grade value
    StudentRecord<int> srInt(3);
    srInt.setId(111111);
    srInt.printGrades();
 
    StudentRecord<char> srChar('B');
    srChar.setId(222222);
    srChar.printGrades();

    StudentRecord<float> srFloat(3.333);
    srFloat.setId(333333);
    srFloat.printGrades();
    
    StudentRecord<string> srString("B-");
    srString.setId(4444);
    srString.printGrades();
    
    return 0;
}

输出:

ID# 111111: 3
 
ID# 222222: B
 
ID# 333333: 3.333
 
ID# 4444: B-

9. Generic Classes Issues

compilers need to know what variable type and how many elements are required for an array at compile time. The information is necessary to allocate memory for the array. C++是一种静态语言,需要在编译的时候知道array的变量类型和元素个数,这样才能给array分配内存。

main.hpp:

//header file for main.cpp

#include<iostream>

using namespace std;
const int SIZE=5;

template <class T>
class StudentRecord
{
    private:
        const int size = SIZE;
        T grades[5];
        int studentId;
    public:
        void setGrades(T* input);
        void setId(int idIn);
        void printGrades();
};

template<class T>
void StudentRecord<T>::setGrades(T* input)
{
    for(int i=0; i<SIZE;++i)
    {
        grades[i] = input[i];
    }
}

template<class T>
void StudentRecord<T>::setId(int idIn)
{
    studentId = idIn;
}

template<class T>
void StudentRecord<T>::printGrades()
{
    std::cout<<"ID# "<<studentId<<": ";
    for(int i=0;i<SIZE;++i)
        std::cout<<grades[i]<<"\n ";
    std::cout<<"\n";
}


main.cpp:

/*Goal: understand an
**issue with memory allocation
**in generic classes
*/
/***This code will not compile without errors*****/
#include "main.hpp"

int main()
{
    //StudentRecord is the generic class
    StudentRecord<int> srInt();
    srInt.setId(111111);
    int arrayInt[SIZE]={4,3,2,1,4};
    srInt.setGrades(arrayInt);
    srInt.printGrades();
 
    StudentRecord<char> srChar();
    srChar.setId(222222);
    char arrayChar[SIZE]={'A','B','C','D','F'};
    srChar.setGrades(arrayChar);
    srChar.printGrades();
   
    StudentRecord<float> srFloat();
    srFloat.setId(333333);
    float arrayFloat[SIZE]={2.75,4.0,3.7,2.8,3.99};
    srFloat.setGrades(arrayFloat);
    srFloat.printGrades();
    
    StudentRecord<string> srString();
    srString.setId(4444);
    string arrayString[SIZE]={"B","B-","C+","B","A"};
    srString.setGrades(arrayString);
    srString.printGrades();
    
    return 0;
}