C++模板类声明和定义分离时候,的显示实例化

为什么模板类的实现放在cpp会出错

编译用到了模板类的编译单元时,编译器需要访问方法或者类的实现,以实例化它们。 如果这些实现不在头文件中,则它们将不可访问,因此编译器将无法实例化模板,进而会导致编译出错。

模板类的几种写法

声明和定义都放在XXX.h中

// MyTpClass.h
template <typename T>
struct MyTpClass
{
    void doTest(T param) { }
};

声明XXX.h和定义在XXX.cpp(分隔开)

// MyTpClass.h
template <typename T>
struct MyTpClass
{
    void doTest(T param);
};

#include "MyTpClass.cpp"




// MyTpClass.cpp
template <typename T>
void MyTpClass<T>::doTest(T param)
{
    //implementation
}

实现放在了MyTpClass.cpp,然而还是include MyTpClass.cpp在了头文件中,只是做了文件的分隔,但是其他文件include了头文件后,还是把实现也包含进去了,跟都放在.h效果类似,只是实现和声明分开,代码可读性更好

声明放在.h文件,定义放在.cpp文件

// MyTpClass.h
// no implementation
template <typename T> struct MyTpClass{ ... };

//----------------------------------------    

// MyTpClass.cpp
// implementation of MyTpClass's methods

// explicit instantiations    //显示实例化
template class MyTpClass<int>;
template class MyTpClass<float>;

// You will only be able to use MyTpClasswith int or float

 

正在的声明和实现分离,include了头文件之后不会把实现的代码也加入到该编译单元。然后需要将所有用到的类型都显式的实例化

什么是实例化

编译器怎么处理模板呢?本质上来说,模板可被编译器产生多种多样函数和类的代码。只有当被使用的时候,编译器才会产生用于这种类型的代码。模板不是直接编译成以后需要的各种类的实现,而是将模板代码解析放入内存中,当编译某个编译单元需要用到该模板,则会按需产生相应的代码。实例化是编译器确定特定模板与特定参数集一起使用并在模板上执行参数替换以生成要编译的类或函数以及最终编译为模板的二进制代码的过程。

有两种类型模板实例化,隐式和显式。

显式的实例化

见第三段代码,Foo.cpp中显式实例化了Foo和Foo。显式实例化会实例化所有的成员函数。

隐式实例化

是一种按需实例化。当你使用一个模板类时,编译器才会进行实例化。例如如果你使用vector,此时编译器才会创建一个vector类型,并且只会实例化所需要的函数。不实例化所有的成员函数主要有两点原因:
1、节省编译时间
2、不同的成员函数对类型属性有一些要求,不实例化可以使得更多的类型可以用到模板类。例如map的operator[]操作符要求value是有默认构造函数的,因为你通过不存在的key访问value的时候会新建一个value,且是需要调用默认构造函数。如果你不需要这个操作,用find和insert也可以达到目标,这样对value的类型就少了一个限制,使得模板类更具有普适性。

特化template时遇到的duplicate symbol问题

stackoverflow上面有案例,详见multiple definition of template specialization when using different objects

Intuitively, when you fully specialize something, it doesn’t depend on a template parameter any more – so unless you make the specialization inline, you need to put it in a .cpp file instead of a .h or you end up violating the one definition rule as David says. Note that when you partially specialize templates, the partial specializations do still depend on one or more template parameters, so they still go in a .h file.
翻译过来:
直观地说,当你完全特化某些东西时,它不再依赖于模板参数,所以除非你使内联专业化,你需要将它放在.cpp文件中而不是.h中,否则你最终会违反大卫说的一个定义规则。 请注意,当您对模板进行部分特化时,部分特化仍然依赖于一个或多个模板参数,因此它们仍然位于.h文件中。
推荐的写法为:
举例,template中static成员的初始化,完全特化实现在.cpp中

template<> int B<A, 1>::a[1] = { };

声明在.h中

template<> int B<A, 1>::a[1];

详见static member initialization for specialized template class

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
智慧校园整体解决方案是响应国家教育信息化政策,结合教育改革和技术创新的产物。该方案以物联网、大数据、人工智能和移动互联技术为基础,旨在打造一个安全、高效、互动且环保的教育环境。方案强调从数字化校园向智慧校园的转变,通过自动数据采集、智能分析和按需服务,实现校园业务的智能化管理。 方案的总体设计原则包括应用至上、分层设计和互联互通,确保系统能够满足不同用户角色的需求,并实现数据和资源的整合与共享。框架设计涵盖了校园安全、管理、教学、环境等多个方面,构建了一个全面的校园应用生态系统。这包括智慧安全系统、校园身份识别、智能排课及选课系统、智慧学习系统、精品录播教室方案等,以支持个性化学习和教学评估。 建设内容突出了智慧安全和智慧管理的重要性。智慧安全管理通过分布式录播系统和紧急预案一键启动功能,增强校园安全预警和事件响应能力。智慧管理系统则利用物联网技术,实现人员和设备的智能管理,提高校园运营效率。 智慧教学部分,方案提供了智慧学习系统和精品录播教室方案,支持专业级学习硬件和智能化网络管理,促进个性化学习和教学资源的高效利用。同时,教学质量评估中心和资源应用平台的建设,旨在提升教学评估的科学性和教育资源的共享性。 智慧环境建设则侧重于基于物联网的设备管理,通过智慧教室管理系统实现教室环境的智能控制和能效管理,打造绿色、节能的校园环境。电子班牌和校园信息发布系统的建设,将作为智慧校园的核心和入口,提供教务、一卡通、图书馆等系统的集成信息。 总体而言,智慧校园整体解决方案通过集成先进技术,不仅提升了校园的信息化水平,而且优化了教学和管理流程,为学生、教师和家长提供了更加便捷、个性化的教育体验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

隨意的風

如果你觉得有帮助,期待你的打赏

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值