c++ 模板总结

本文总结了C++模板的相关知识,包括模板声明与定义分离的问题及其解决方案,派生类继承模板类,模板函数类型推导的规则,以及模板类中的虚函数特性。详细探讨了成员模板函数无法虚化的原因,并介绍了模板类的虚表机制和编译器如何编译模板函数。同时,文章还提及了C++标准库中的type_traits及其在类型萃取中的应用。
摘要由CSDN通过智能技术生成
模板

模板被称为c++ 下的编译器多态。最近写模板遇到了一些坑总结下。

模板 声明与定义分离

c++ 惯有的源文件模式都是 将声明写到 .h 文件中,将实现写到 .cpp 文件中。但是对于模板来说,如果我们把 模板类或者模板函数这样分离实现,当链接的时候会报链接错误。
本质上,这个错误因为 当其他源文件 包含 模板的头文件的时候,编译器编译当前源文件时会认为该 模板 已经有了相应实现,具体的实现就在相应的模板源文件中,编译器不会再去实例化相应的模板函数 或者 模板的成员函数 ,它会交给 链接器去链接。
这个时候因为虽然 模板的源文件有了 相应的实现,但是如果 没有使用相应的模板函数 或者 模板类 的话, 编译器并不会给该模板源文件的模板进行实例化 ,所以等链接器链接的时候会报链接错误,如下demo。

templateA.h 
template <class T>
class TemplateA {
 public:
  void Fun();
};
templateA.cpp
template <class T>
void TemplateA<T>::Fun() {} 

main.cc 
int main() 
{
  templateA<int> test_a;
  test_a.Fun();
  return 0;
}
main.cc:(.text+0x32): undefined reference to `TemplateA<int>::Fun()

所以解决方案俩种

  1. 将模板的实现和定义全放到头文件中
  2. 在 .cpp 中使用 template 关键字进行显式实例化
templateA.cpp 
template <class T>
void TemplateA<T>::Fun() {} 

//显示实例化
template class TemplateA<int>;

但是显示实例化虽然一定程度实现了 声明与实现分离,但是这样依赖于调用者的实现,每多一个类型, template.cpp 文件就得多一行相应的实例化声明,接着相应的 template.cpp 就得被重新编译。

派生类继承模板类

有的时候我们想 继承一个模板类的具体的实例化,这样是可以的。当需要重写 模板类的虚函数时,只要给出具体类型的实现即可。

templateA.h 
template <typename Key>
class Table {
  public:
    Table() {}
     
    virtual Fun (Key key) = 0;
};

main.cc 
class WoodTable : public Table<int> {
  public:
    WoodTable()
     {}
 
    virtual Fun(int key) 
    {}
};
模板函数类型推导

参数推导顺序 从 右 到 左 参数以此进行推导。

模板类中的虚函数
  1. 模板类的成员函数是可以是 虚函数的。
  2. 但是 成员模板函数不能是虚函数
    这俩个很绕口,模板类的成员函数,它可以使用 模板类的模板参数,并且可以虚化(也就是可以是虚函数)。但是在模板类 / 类中定义一个 成员模板函数,把它声明成 虚函数,编译器会报错。
模板类的成员函数虚化

下面的这个模板类的成员函数,虽然它里面也使用了模板

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值