C++学习笔记之 模板

模板

概念

模板是泛型编程的基础,泛型编程即以一种独立于任何特定类型的方式编写代码,即不具体制定数据类型

模板是创建泛型类或函数的蓝图或公式

函数模板

基本语法

#include <iostream>
#include <cstdio>

using namespace std;

// 函数模板实现通用数据类型交换
template<typename T> // T属于通用数据类型
void mySwap(T &a,T &b) { // 模板可以将类型参数化
    T temp = a;
    a = b;
    b = temp;
}

// 使用函数模板
void test01() {
    // 1. 自动类型推导
    int a = 0,b = 1;
    cout << "a = " << a << ",b = " << b << endl;
    mySwap(a,b);
    cout << "a = " << a << ",b = " << b << endl;
    
    // 2. 显式指定类型
    mySwap<int>(a,b);
    cout << "a = " << a << ",b = " << b << endl;
    mySwap(a,b);
    cout << "a = " << a << ",b = " << b << endl;
    
    // 注意:模板必须推导出T的类型才能使用,否则不能单独使用
}

int main() {
    test01();

    return EXIT_SUCCESS;
}
a = 0,b = 1
a = 1,b = 0
a = 0,b = 1
a = 1,b = 0

函数模板与普通函数区别

  1. 普通函数可以发生隐式类型转化
  2. 如果普通函数和函数模板(同名)都可以匹配,优先匹配普通函数
  3. 如果要强制调用函数模板,则要加空模板参数列表mySwap<>(a,b)
  4. 函数模板也可以产生函数重载
  5. 如果函数模板可以产生更好的匹配,那么优先匹配函数模板

函数模板的局限和解决

#include <iostream>

using namespace std;

class Person
{
public:
    int m_Age;
    Person(int age) : m_Age(age) {
        ;
    }
};

// 模板并不真正通用
// 对于特殊数据类型,可以具体化实现
template<class T>
bool myCompare(T &a, T &b) {
    return a == b;
}

// 利用具体化实现,解决特殊数据类型
// 语法:template<> 函数名 + 具体实现
template<> bool myCompare(Person &a, Person &b) {
    return a.m_Age == b.m_Age;
}

int main() {
    Person p1 = Person(18);
    Person p2 = Person(20);
    cout << myCompare(p1,p2) << endl;

    return EXIT_SUCCESS;
}
0

类模板

基本语法

#include <iostream>
#include <string>

using namespace std;

// 模板中也可以指定默认参数
template<class T1,class T2 = int>
class Person
{
public:
    T1 m_Name;
    T2 m_Age;
    
    Person(T1 name, T2 age) {
        this->m_Age = age;
        this->m_Name = name;
    }
};

int main() {
    // Person p(18,"Tom"); 类模板使用时,不可以自动类型推导,必须显式指定
    Person <string,int>p("Tom",18);

    return EXIT_SUCCESS;
}

类模板中成员函数创建时机

#include<iostream>

using namespace std;

class Person1
{
public:
    void showPerson1()
    {
        cout << "showPerson1" << endl;
    }
};

class Person2
{
public:
    void showPerson2()
    {
        cout << "showPerson2" << endl;
    }
};


//类模板中成员函数并不是一开始创建,而是在替换T后,才去生成

template<class T>
class testClass
{
public:
    void func1()
    {
        obj.showPerson1();
    }

    void func2()
    {
        obj.showPerson2();
    }

    T obj;
};


void test01()
{
    testClass<Person2>tc;
    //tc.func1();
    tc.func2();

}


int main(){

    test01();

    return EXIT_SUCCESS;
}

类模板做函数参数

#include<iostream>
using namespace std;
#include <string>

//模板中 也可以使用默认参数
template<class T1, class T2>
class Person
{
public:

	Person(T1 name, T2 age)
	{
		this->m_Name = name;
		this->m_Age = age;
	}

	void showPerson()
	{
		cout << "姓名: " << this->m_Name << " 年龄: " << this->m_Age << endl;
	}

	T1 m_Name;
	T2 m_Age;
};

//1、指定传入类型
void doWork(Person <string, int>&p)
{
	p.showPerson();
}

void test01()
{
	Person <string,int>p1("Tom", 100);
	doWork(p1);
}

//2、将参数模板化
template<class T1,class T2>
void doWork2(Person <T1, T2>&p)
{
	cout << "T1 = " << typeid(T1).name() << endl;
	cout << "T2 = " << typeid(T2).name() << endl;
	p.showPerson();
}

void test02()
{
	Person <string, int>p1("Jerry", 100);
	doWork2(p1);
}


//3、将类模板化
template<class T>
void doWork3(T &p)
{
	cout << "T = " << typeid(T).name() << endl;
	p.showPerson();
}

void test03()
{
	Person <string, int>p1("Bill", 100);
	doWork3(p1);
}



int main(){

	//test01();
	//test02();
	test03();

	system("pause");
	return EXIT_SUCCESS;
}
T = 6PersonINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEiE
姓名: Bill 年龄: 100

类模板遇到继承时的问题和解决

#include<iostream>
using namespace std;

template<class T>
class Base
{
public:
	T m_A;
};

//子类在继承时,必须确定出父类的T的数据类型,否则无法给T分配内存空间
class Son :public Base<int>
{

};


template<class T>
class Base2
{
public:
	T m_A;
};

template<class T1, class T2>
class Son2 :public Base2<T2>
{
public:
	Son2()
	{
		cout << "T1的类型为: " << typeid(T1).name() << endl;
		cout << "T2的类型为: " << typeid(T2).name() << endl;
	}

	T1 m_B;
};


void test01()
{
	Son2<int, double> s;
}

int main(){

	test01();

	system("pause");
	return EXIT_SUCCESS;
}
T1的类型为: i
T2的类型为: d

类模板成员函数类外实现

#include<iostream>
using namespace std;
#include <string>


template<class T1, class T2>
class Person
{
public:

    Person(T1 name, T2 age);
    //{
    //	this->m_Name = name;
    //	this->m_Age = age;
    //}

    void showPerson();
    //{
    //	cout << "姓名: " << this->m_Name << " 年龄: " << this->m_Age << endl;
    //}

    T1 m_Name;
    T2 m_Age;
};

template<class T1,class T2>
Person<T1,T2>::Person(T1 name, T2 age)
{
    this->m_Name = name;
    this->m_Age = age;
}

template<class T1, class T2>
void Person<T1,T2>::showPerson()
{
    cout << "姓名: " << this->m_Name << " 年龄: " << this->m_Age << endl;
}


void test01()
{
    Person<string, int>p("aaa", 10);
    p.showPerson();
}

int main(){
    test01();
    return EXIT_SUCCESS;
}
姓名: aaa 年龄: 10

类模板和友元

类内实现

#include<iostream>
using namespace std;
#include <string>

template<class T1,class T2>
class Person
{

	friend void printPerson(Person<T1, T2>& p)
	{
		cout << "姓名: " << p.m_Name << " 年龄: " << p.m_Age << endl;
	}

public:

	Person(T1 name, T2 age)
	{
		this->m_Name = name;
		this->m_Age = age;
	}

private:
	T1 m_Name;
	T2 m_Age;
};


void test01()
{
	Person<string, int>p("Tom", 111);

	printPerson(p);
}

int main(){

	test01();

	return EXIT_SUCCESS;
}

类外实现

#include<iostream>
using namespace std;
#include <string>

//先让编译器看到Person类声明
template<class T1, class T2>class Person;

//先让编译器看到函数模板 printPerson的存在
template<class T1, class T2> void printPerson(Person<T1, T2>& p);


template<class T1, class T2>
void printPerson2(Person<T1, T2>& p)
{
	cout << "姓名: " << p.m_Name << " 年龄: " << p.m_Age << endl;
}

template<class T1, class T2>
class Person
{

	friend void printPerson<>(Person<T1, T2>& p);

	friend void printPerson2<>(Person<T1, T2>& p);

public:

	Person(T1 name, T2 age)
	{
		this->m_Name = name;
		this->m_Age = age;
	}

private:
	T1 m_Name;
	T2 m_Age;
};

template<class T1,class T2>
void printPerson(Person<T1, T2>& p)
{
	cout << "姓名: " << p.m_Name << " 年龄: " << p.m_Age << endl;
}


void test01()
{
	Person<string, int>p("Tom", 222);

	printPerson(p);
	printPerson2(p);
}

int main(){

	test01();

	return EXIT_SUCCESS;
}
原文地址:https://www.cnblogs.com/zhujiangyu/p/14091394.html