有关template,为什么在.h文件里定义template,而不用在实现文件里定义?

时间:2022-03-26 20:36:09
我在vc++中将template function的申明写在.h文件里,将实现写在.cpp文件里,但不能通过,但是我把.cpp文件删除之后(不删还不行),将定义写在.h文件里,就通过了,觉得有点不可理解,原因看了下面这本书。

大师stanley B. Lippman在他的essential c++中写到:“函数的定义只能有一份,不过倒是可以有许多份声明。我们不把函数的定义纳入头文件,因为同一个程序的多个代码文件可能都会含入这个头文件。”

上述情况却有出入,请大家给我解释一下!!

7 个解决方案

#1


模板的情况比较特殊。具体可以看看c++ primer

#2


应该没有这种事情吧?
是不是你的include有问题呀?

<<有关template,为什么在.h文件里定义template,而不用在实现文件里定义?>>

其实这样也有好处,因为template是所有的类型都兼容的,
不会有同样的作用的不同定义的template出现,所以,
把template定义在.h里面是合理的,不然,你每次调用它,
你都要重新定义,多麻烦,而且,代码又重复了!

#3


你需要好好了解一下模板是如何生成实例的(即template instantiation)。我尽量简单地说明一下你碰到的问题的原因。

当模板生成实例时,模板的声明和定义都必须产生对应的实例。如果声明和定义都在一个文件中,编译器很容易做这件事。但如果它们是在不同的文件里,编译器就必须想办法找到定义的文件名(否则无法生成实例)。它一般是通过规定来做的,比如定义文件的名字和声明文件的名字相同(但扩展名不同)或定义文件名与类名字相同。有不少编译器干脆规定定义和声明必须在同一个文件里。

顺便提个问题:
为什么下面的声明是无意义的(或说有矛盾)?
template <typename T> static T foo(T t);

#4


不知道codingcoding所说的c++prime里是怎么解释的?
do_do说的也很有道理,不知道还有没其他解释?
听人说vc++对template支持不好,不知道是哪方面,是不是真有其事?

#5


template是内部链接的(internal linkage),要在一个文件中引用一个模板,这个文件就必须包含对这个模板的定义(不是只声明).这个性质和内联函数是一样的,引用一个内联函数的文件也必须包含对它的定义。Lippman所说的函数是普通函数,它们是外部链接的(external linkage),在引用的地方只要包含它们的声明就可以了。
    不过用export关键字可以实现只包含声明就引用模板:
//template.h     声明
template<class T>void f(T a);   //template.cpp
#include "template.h"   定义
export template<class T>void f(T a)   { return; }  
//somefile.cpp   引用文件
# include "template.h"     //只要包含头文件中的声明
void somefunc()
{
    int a;
    f(a);
}

#6


定义template 与一般的定义class不同!
把template的声明与定义都写在头文件中是一种很好的风格,Bjarne Stroustrup说的!
具体怎么说的来着我忘了,还是看书吧!(我看的是The C++ Programming Language)

#7


用export关键字输出模板
看C++ primer有关模板的部分,有详细说明

#1


模板的情况比较特殊。具体可以看看c++ primer

#2


应该没有这种事情吧?
是不是你的include有问题呀?

<<有关template,为什么在.h文件里定义template,而不用在实现文件里定义?>>

其实这样也有好处,因为template是所有的类型都兼容的,
不会有同样的作用的不同定义的template出现,所以,
把template定义在.h里面是合理的,不然,你每次调用它,
你都要重新定义,多麻烦,而且,代码又重复了!

#3


你需要好好了解一下模板是如何生成实例的(即template instantiation)。我尽量简单地说明一下你碰到的问题的原因。

当模板生成实例时,模板的声明和定义都必须产生对应的实例。如果声明和定义都在一个文件中,编译器很容易做这件事。但如果它们是在不同的文件里,编译器就必须想办法找到定义的文件名(否则无法生成实例)。它一般是通过规定来做的,比如定义文件的名字和声明文件的名字相同(但扩展名不同)或定义文件名与类名字相同。有不少编译器干脆规定定义和声明必须在同一个文件里。

顺便提个问题:
为什么下面的声明是无意义的(或说有矛盾)?
template <typename T> static T foo(T t);

#4


不知道codingcoding所说的c++prime里是怎么解释的?
do_do说的也很有道理,不知道还有没其他解释?
听人说vc++对template支持不好,不知道是哪方面,是不是真有其事?

#5


template是内部链接的(internal linkage),要在一个文件中引用一个模板,这个文件就必须包含对这个模板的定义(不是只声明).这个性质和内联函数是一样的,引用一个内联函数的文件也必须包含对它的定义。Lippman所说的函数是普通函数,它们是外部链接的(external linkage),在引用的地方只要包含它们的声明就可以了。
    不过用export关键字可以实现只包含声明就引用模板:
//template.h     声明
template<class T>void f(T a);   //template.cpp
#include "template.h"   定义
export template<class T>void f(T a)   { return; }  
//somefile.cpp   引用文件
# include "template.h"     //只要包含头文件中的声明
void somefunc()
{
    int a;
    f(a);
}

#6


定义template 与一般的定义class不同!
把template的声明与定义都写在头文件中是一种很好的风格,Bjarne Stroustrup说的!
具体怎么说的来着我忘了,还是看书吧!(我看的是The C++ Programming Language)

#7


用export关键字输出模板
看C++ primer有关模板的部分,有详细说明