c/c++模板的定义和实现分开的问题及其解决方案

注意c/c++模板的定义和实现- -
                                       
定义一个类一般都是在头文件中进行类声明,在cpp文件中实现,但使用模板时应注意目前的C++编译器还无法分离编译,最好将实现代码和声明代码均放在头文件中。如:

test.h

template<class T>class CTest{ public:    T& GetValue();    void SetValue(const T& _Value);protected:    T m_Value; };

test.cpp

template<class T>T& CTest<T>::GetValue(){     return m_Value; }template<class T>void CTest<T>::SetValue(const T& _Value){     m_Value = _Value; }

在这儿test.cpp中的内容应放在test.h中,否则在生成最终可执行程序时就会出现错误(在链接时会出错)。因为在编译时模板并不能生成真正的二进制代码,而是在编译调用模板类或函数的CPP文件时才会去找对应的模板声明和实现,在这种情况下编译器是不知道实现模板类或函数的CPP文件的存在,所以它只能找到模板类或函数的声明而找不到实现,而只好创建一个符号寄希望于链接程序找地址。但模板类或函数的实现并不能被编译成二进制代码,结果链接程序找不到地址只好报错了。

《C++编程思想》第15章(第300页)说明了原因:模板定义很特殊。由template<…>处理的任何东西都意味着编译器在当时不为它分配存储空间,它一直处于等待状态直到被一个模板实例告知。在编译器和连接器的某一处,有一机制能去掉指定模板的多重定义。所以为了容易使用,几乎总是在头文件中放置全部的模板声明和定义。

沈公子在 2005年2月15日11:19星期二 评论: 
你说的有误,要将实现代码放在cpp文件中,否则编译时所有包含头文件的单元都要额外的编译时间。
只要在实现中的模板函数之前加上export就可以避免你说的链接错误,这是STL编程时的技巧之一。

原文转自:http://blog.csdn.net/jolin678/article/details/46712359

原作者为 JolinSky。请尊重原作者版权

时间: 2025-01-02 17:54:27

c/c++模板的定义和实现分开的问题及其解决方案的相关文章

读书笔记 effective c++ Item 46 如果想进行类型转换,在模板内部定义非成员函数

1. 问题的引入——将operator*模板化 Item 24中解释了为什么对于所有参数的隐式类型转换,只有非成员函数是合格的,并且使用了一个为Rational 类创建的operator*函数作为实例.在继续之前建议你先回顾一下这个例子,因为这个条款的讨论是对它的扩展,我们会对Item 24的实例做一些看上去无伤大雅的修改:对Rational和opeartor*同时进行模板化: 1 template<typename T> 2 class Rational { 3 public: 4 Rati

freemarker 模板中定义变量

在模板中可以定义三种类型的变量: 简单变量:它能从模板中的任何位置来访问,或者从使用 include 指令引入的模板访问.可以使用 assign 或 macro 指令来创建或替换这些变量. 局部变量:它们只能被设置在宏定义体内,而且只在宏内可见.一个局部变量的生存周期只是宏的调用过程.可以使用 local 指令在宏定义体内创建或替换局部变量. 循环变量:循环变量是由指令(如 list )自动创建的,而且它们只在指令的开始和结束标记内有效.宏的参数是局部变量而不是循环变量. 示例:使用 assig

C++类模板声明与定义为何不能分开

C++中每一个对象所占用的空间大小,是在编译的时候就确定的,在模板类没有真正的被使用之前,编译器是无法知道,模板类中使用模板类型的对象的所占用的空间的大小的.只有模板被真正使用的时候,编译器才知道,模板套用的是什么类型,应该分配多少空间.这也就是模板类为什么只是称之为模板,而不是泛型的缘故. 既然是在编译的时候,根据套用的不同类型进行编译,那么,套用不同类型的模板类实际上就是两个不同的类型,也就是说,stack<int>和stack<char>是两个不同的数据类型,他们共同的成员函

C++模板 静态成员 定义(实例化)

问一个问题: 考虑一个模板: template <typename T> class Test{ public: static std::string info; }; 对于下面若干种定义方式.哪些是对的(通过编译)? template <> string Test<int>::info("123"); template <typename T> string Test<T>::info("123"); t

函数模板的定义和使用

函数模板:建立一个通用函数,其函数类型和形参类型不具体指定,用一个虚拟的类型来代表,这个通用函数就称为函数模板. 一般形式:template<typename T> 通用函数定义 注意:关键字typename是类型名,只适用于函数体相同.函数的参数个数相同而类型不同的情况. 例:用函数模板实现求3个数中的最大者. 程序: #include<iostream> using namespace std; template<typename T>//模板声明,T为类型参数 T

模板初步——定义模板

一.关键点 定义函数模板&类模板 模板参数列表:非类型参数 类模板类名的使用:依据作用域是否加上模板类型 类模板和友元:设置友好关系 模板参数:使用类的类型成员.默认模板实参 成员模板的使用:非模板类的成员模板.模板类的成员模板 二.定义函数模板 //模板参数T是一个类型 template <typename T> bool cmp(const T &a, const T &b) { return a < b; } //模板参数N是一个非类型参数 template

C++模板的定义一定要在头文件中 - LNK2019无法链接的外部符号,LNK1120无法解析的外部命令

编译器在模板函数的调用处,才最终知道如何生成代码. 模板函数的不能像普通的成员函数那样声明于头文件而定义在cpp源文件,而是一定要定义在头文件中. 若像普通成员函数那样声明和定义,单个文件可以编译通过,但被其他文件使用时会报LNK2019,LNK1120错误: 原文地址:https://www.cnblogs.com/dylanchu/p/12315493.html

django 模板中定义临时列表

<ul class="num_t clr"> {% for obj in ""|ljust:"10" %} <li>{{ forloop.counter }}</li> {% endfor %} </ul> 官网是这样使用: ljust Left-aligns the value in a field of a given width. Argument: field size For exampl

关于ThinPHP开启Smarty模板后,不能使用success、error方法解决方案

解决方法:自己在入口文件定义一个方法,控制跳转,样式自己定义,哈哈!!! index.php代码 <?php // 开发调试模式true false 生产模式define('APP_DEBUG',True);define("HOME_IMG",'/shop/Home/Common/images/');define("HOME_CSS",'/shop/Home/Common/css/');define("HOME_JS",'/shop/Hom