Template

函数模板和类模板

函数模板和类模板本质上可以理解成泛型函数和泛型类,但是它们实际上是模板,而不是真正的函数和类,添加template<typename 类型1,typename类型2,…>并替换掉原有硬编码类型的声明即可

函数模板
函数模板的特点就是其函数可以通过模板自动推导出类型,使用函数模板需要注意:
1.数据类型一定是一致的才可以使用

template<typename T>
void Swap(T& a, T& b) {
    T temp = a;
    a = b;
    b = temp;
}
void main() {
    string str = "head";
    int a = 1;
    Swap(str, a); //此时编译器会报错,因为两个数据是不同类型
}

2.模板必须要确认出形参类型,也就是上面T的类型要先确认才可以使用

template<typename T>
void test() {

}
void main() {
    test();      //编译器报错,没有确定类型
    test<int>(); //可以使用显示指定类型的方式,给T一个类型,此时是可以使用的
}

类模板
与函数模板的区别:
1.类模板不能像函数模板那样自动推导出类型

template<class PhoneNumber,class Name>
class Contacts {
private:
    PhoneNumber pNumber;
    Name name;
public:
    Contacts(int pNumber, string name) {
        this->pNumber = pNumber;
        this->name = name;
    }
    void readContact() {
        cout << name << ' ' << pNumber;
    }
};

void main() {  
    Contacts contact(123456789,"li");   //error,类函数不能自动推导出类型
    Contacts<int,string> contact(123456789, "li");
    contact.readContact();
}

2.类模板在形参表内可有默认参数

template<class PhoneNumber,class Name = string>
class Contacts {
   void readContact() {
        cout << name << ' ' << pNumber;
    }
};

void main() {  
    Contacts<int> contact(123456789, "li");//此时name已是默认的string类型
    contact.readContact();
}

3.类模板对象做函数参数
1)直接指定传参的类型

template<class PhoneNumber,class Name>
class Contacts {
    void readContact() {  
        cout << name << ' ' << pNumber;
    }
    void print(Contacts<int, string>& contact) { //形参与需要引用的实参类型相同
        contact.readContact();
    }
};
void main() {  
    Contacts<int,string> contact(123456789, "li");
    contact.print(contact);
}

2)将参数也变成模板形式

template<class PhoneNumber,class Name> /
class Contacts {
    void readContact() {  
        cout << name << ' ' << pNumber;
    }
    void print(Contacts<PhoneNumber,Name>& contact) {//参数模板化
        contact.readContact();
    }
};

优缺点
优点:
1.灵活性, 可重用性,可扩展性
2.可以大大减少开发时间,模板可以把用同一个算法去适应不同的数据类型,在编译时确定具体的数据类型
3.模板模拟多态要比C++类继承实现多态效率要高,无虚函数,无继承
缺点:
1.易读性比较不好,调试比较困难
2.模板的数据类型只能在编译时才能被确定
3.所有用于基于模板算法的实现必须包含在整个设计的.h头文件中,当工程比较大的时候编译时间较长。

模板编译与链接
当编译器遇到一个template时,不能够立马为他产生机器代码,它必须等到template被指定某种类型,也就是说函数模板和类模板的完整定义将出现在template被使用的每一个角落,才能够确定编译内容,否则编译器没有足够的信息产生机器代码

对于不同的编译器,其对模板的编译和链接技术也会有所不同,其中一个常用的技术称之为Smart,其基本原理如下
1.模板编译时,以每个cpp文件为编译单位,实例化该文件中的函数模板和类模板
2.链接器在链接每个目标文件时,会检测是否存在相同的实例;有存在相同的实例版本,则删除一个重复的实例,保证模板实例化没有重复存在

比如我们有一个程序包含A.cpp和B.cpp,它们都调用了CThree模板类,在A文件中定义了int和double型的模板类,在B文件中定义了int和float型模板类;在编译器编译时.cpp文件为编译基础,生成A.obj和B.obj目标文件,即使A.obj和B.obj存在重复的实例版本,但是在链接时,链接器会把所有冗余的模板示例代码删除,保证exe中的实例时唯一的

模板类和类模板是两种完全不同的东西,类模板强调的是模板,专门用于产生类的模子,而模板类是类模板实例化后的结果

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值