Improving C + + Programming Chapter 1 template

I. concept of templates

Template is to establish a general mold, which greatly improves the reusability
Another programming idea of C + + is called generic programming, which mainly uses template
C + + improves two template mechanisms: function template and class template

Two, template characteristics

  1. The template cannot be used directly. It is just a framework
  2. The universality of templates is not everything

3, Function template

Function template function: create a general function whose return value type and formal parameter type can be represented by a virtual type without specifying

1. Grammar

template<typename T>
Function declaration or definition

Template -- declare the creation of a template
typename -- indicates that the symbol behind it is a data structure, which can be replaced by class
T -- General data type, the name can be replaced, usually in uppercase letters

Sample code

template<typename T> //Declare a template and tell the compiler not to report an error for the T immediately following the code. T is a general data type
void Myswap(T& a, T& b)
{
	T temp = a;
	a = b;
	b = temp;
}
int main()
{
	int a = 10, b = 50;
	cout << a << " " << b << endl;
	Myswap(a, b); //1. Automatic type derivation
	cout << a << " " << b << endl;
	Myswap<int>(a, b);//2. Displays the specified type
}

2. Precautions

For automatic type derivation, a consistent data type T must be derived before it can be used
The template can be used only after the data type of T is determined

3. Differences between ordinary functions and function templates

  1. Automatic type conversion (implicit type conversion) can occur when ordinary function calls
  2. When a function template is called, if automatic type derivation occurs, implicit type conversion will not occur
  3. Implicit type conversion can occur if the specified type is displayed

4. Call rules for ordinary functions and function templates

  1. If both ordinary functions and function templates can be implemented, call ordinary functions first
  2. You can force a function template to be called through an empty template parameter list
void Myswap(T& a, T& b)
{
	cout << "Template called!" << endl; 
	T temp = a;
	a = b;
	b = temp;
}
void Myswap(int& a, int& b)
{
	cout << "function called!" << endl;
	int temp = a;
	a = b;
	b = temp;
}
int main()
{
	int a = 20, b = 10;
	cout << a << " " << b << endl;
	Myswap<>(a, b);//You can force a function template to be called through an empty template parameter list
	cout << a << " " << b << endl;
	return 0;
}
  1. Function templates can also be overloaded
  2. If the function template can match better, call the function template first
template<class T>
void Myswap(T& a, T& b)
{
	cout << "Template called!" << endl; 
	T temp = a;
	a = b;
	b = temp;
}
void Myswap(char& a, char& b)
{
	cout << "function called!" << endl;
	int temp = a;
	a = b;
	b = temp;
}
int main()
{
	int a = 20, b = 10;
	cout << a << " " << b << endl;
	Myswap(a, b);//Function templates can produce better matches
	cout << a << " " << b << endl;
	return 0;
}

Summary: since the function template is provided, it is better not to provide ordinary functions, otherwise ambiguity may occur

4, Class template

Class template function:
Establish a general class. The member data types in the class can be represented by a virtual type without specific formulation

1. Grammar

template<typename T>
class

Template -- declare the creation of a template
typename -- indicates that the symbol behind it is a data structure, which can be replaced by class
T -- General data type, the name can be replaced, usually in uppercase letters

Code example

template<class NameType,class AgeType>
class Person
{
public:
	NameType name;
	AgeType age;
	Person(NameType name, AgeType age)
	{
		this->name = name;
		this->age = age; 
	}
};

int main()
{
	Person<string,int> p1("yxc", 18); //Type must be declared
}

2. Difference between class template and function template

There are two main differences between class templates and function templates:

  1. Class templates do not use automatic type derivation
  2. Class templates can have parameter constructs in the template parameter list
template<class NameType,class AgeType = int> //You can specify the type in the parameter list
class Person
{
public:
	NameType name;
	AgeType age;
	Person(NameType name, AgeType age)
	{
		this->name = name;
		this->age = age; 
	}
	void ShowInfo()
	{
		cout << "Name: " << name << " Age:" << age << endl;
	}
};

int main()
{
	Person<string> p1("yxc", 18); //When specified, it does not need to be declared in the argument list
	p1.ShowInfo();
	return 0;
}

5, Limitations of templates

The versatility of templates is not everything

  • The generalization of user-defined types can be solved by using specific templates
  • Learning templates is not to write templates, but to use the templates provided by the system in STL

6, Creation time of member function in class template

The member function in the class template is created only when it is called

7, Class template object as function parameter

Three incoming modes

  1. Specify the type passed in -- directly display the data type of the object
  2. Parameter instantiation -- change the parameters in the object into templates for transfer
  3. Whole class templating -- passing this object type Templating
void ShowInfo1(Person<string,int>&p) //1. Specify incoming type
{
	cout << "Name: " << p.name << " Age:" << p.age << endl;
}

template<class T1,class T2> //2. Parameter Templating
void ShowInfo2(Person<T1,T2>&p)
{
	cout << "Name: " << p.name << " Age:" << p.age << endl;
	cout << "T1 The type of is" << typeid(T1).name() << " T2 The type of is" << typeid(T2).name() << endl;
}

template<class T>
void ShowInfo3(T& p) //3. Template the whole object
{
	cout << "Name: " << p.name << " Age:" << p.age << endl;
	cout << "T The type of is" << typeid(p).name() << endl;
}

8, Class template and inheritance

When class templates encounter inheritance, you should pay attention to the following points:

  • When the parent class inherited by a subclass is a class template, the subclass shall specify the type of T in the parent class when declaring
  • If not specified, the compiler cannot allocate memory to subclasses
  • If you want to flexibly specify the type of T in the parent class, the child class also needs to become a class template
template<class T>
class Base
{
public:
	T m;
};
class Son :public Base<int> //The type of T must be specified before it can be assigned to a subclass
{
public:
	Son()
	{
		cout << typeid(m).name() << endl;
	}
};

//If you want to flexibly specify the T type in the parent class, the subclass also needs to change the class template
template<class T1,class T2>
class Son2 :public Base<T1>
{
public:
	T2 obj;
	Son2()
	{
		cout << typeid(this->m).name() << " " << typeid(obj).name() << endl;
	}
};
int main()
{
	Son s1;
	Son2<char,int> s;
	return 0;
}

9, Class template member function out of class implementation

When the class template member function is implemented outside the class, the template parameter list needs to be added

template<class T1,class T2>
class Person
{
public:
	T1 name;
	T2 age;
	Person(T1 name, T2 age);
	void showPerson();
};

template<class T1,class T2>
Person<T1,T2>::Person(T1 name, T2 age)//Outside class implementation of constructor of template class
{
	this->name = name;
	this->age = age;
}

template<class T1,class T2>
void Person<T1, T2>::showPerson() //The member function of the template class is implemented outside the class
{
	cout << this->name << " " << this->age << endl;
}

10, Class template is written in files

Problem: the creation time of the member function in the class template is in the calling stage, resulting in the link failure when writing the file
solve
Include directly cpp source file
Write the declaration and implementation to the same file and change the suffix to hpp, hpp is the name of the contract, not mandatory

The first solution: directly include the cpp header file

The second solution is to cpp and h write the contents together and change the suffix to hpp file

11, Class templates and friends

Implementation within the class of global functions - just declare friends within the class and implement them (more often used)
Out of class implementation of global functions - the compiler needs to know the existence of global functions in advance

template<class T1,class T2> //Let the compiler guide the existence of the Person class in advance
class Person;

template<class T1, class T2>//Let the compiler know the existence of global functions in advance
void showPerson(Person<T1, T2>& p)
{
	cout << p.name << " " << p.age << endl;
}

template<class T1, class T2>
class Person
{
	friend void showPerson<>(Person<T1,T2>& p); //The global function is implemented outside the class. As a friend of the class template, you need to add an empty template parameter list
private:
	T1 name;
	T2 age;
public:
	Person(T1 name, T2 age);
};

template<class T1, class T2>
Person<T1, T2>::Person(T1 name, T2 age)//Outside class implementation of constructor of template class
{
	this->name = name;
	this->age = age;
}

int main()
{
	Person<string,int> p1("yxc", 18);
	showPerson(p1);
	return 0;
}

Keywords: C++

Added by kickstart on Tue, 11 Jan 2022 08:22:42 +0200