您的位置:首页 > 其它

模板类的定义与声明

2011-12-27 18:00 295 查看
写了一个模板类,类似其它类那样把定义与声明分开,结果发现只是引用.h文件根本找不到函数的定义。查看相关资料发现如下解释

模板是不是一个类或函数。 模板是一个“模式”,编译器用来生成的相似的或者函数

为了让编译器生成的代码,它必须同时看到模板的定义(不只是声明)和特定类型/任何用于“fill in”模板的类型。例如,如果你想使用一个foo<int>,编译器必须同时看到foo模板和你要调用具体的foo<int>。

编译器可能不记得另外一个.cpp文件的细节,当编译其他.cpp文件的时候。它可以 ,但大多数都没有,如果你正在阅读本FAQ,它几乎肯定不会。顺便说一句,这就是所谓的“独立编译模型”。

现在,基于这些事实,下面是一个范例,它表明为什么是这个样子。假设你有一个这样的模板Foo声明:

template<typename T>

class Foo {

public:

Foo();

void someMethod(T x);

private:

T x;

};

类似地,模板成员函数的定义:

template<typename T>

Foo<T>::Foo()

{

...

}

template<typename T>

void Foo<T>::someMethod(T x)

{

...

}

现在,假设在文件Bar.cpp的一些代码要使用foo<int>:

// Bar.cpp

void blah_blah_blah()

{

...

Foo<int> f;

f.someMethod(5);

...

}

显然,某人某地将不得不调用“模式”的构造函数,和someMethod()函数以及做T为int的实例化。但是,如果你把构造函数和someMethod()的定义放到文件Foo.cpp,当编译Foo.cpp时,编译器将看到模板代码;当编译Bar.cpp时,编译器将看到foo<int>。但任何时候决不会同时看到模板代码和foo<int>。因此,通过上面的2号规则,它根本不会产生foo <int>::someMethod()的代码

解决方法:

1.把声明跟定义写在一个文件

2,在使用的时候包含.h及cpp

例如,考虑foo.h头文件包含以下模板函数声明:

// File "foo.h"

template<typename T>

extern void foo();

现在假设文件foo.cpp实际上定义的模板函数:

// File "foo.cpp"

#include <iostream>

#include "foo.h"

template<typename T>

void foo()

{

std::cout << "Here I am!\n";

}

假设文件main.cpp中使用这个模板函数通过调用foo<int>():

// File "main.cpp"

#include "foo.h"

int main()

{

foo<int>();

...

}

如果你编译和(试图)链接这两个.cpp文件,大多数编译器将生成链接错误。有三种的解决方案。第一个解决方案是物理上在.h文件中定义,即使它不是一个内联函数。这种解决办法可能(或可能不会!)造成重大代码膨胀,意味着可执行文件的大小可能会显显著增加(或者,如果你的编译器足够聪明,可能不会这么做)。

另一个解决办法是保留定义在.cpp文件中,只添加行template void foo<int>()到.cpp文件:

// File "foo.cpp"

#include <iostream>

#include "foo.h"

template<typename T> void foo()

{

std::cout << "Here I am!\n";

}

template void foo<int>();

如果你不能修改foo.cpp,只需创建一个新的.cpp文件,例如foo-impl.cpp如下:

// File "foo-impl.cpp"

#include "foo.cpp"

template void foo<int>();

请注意, foo-impl.cpp文件包含.cpp文件,而不是.h文件。如果你觉着这样很乱,跳个踢踏舞,想想堪萨斯,跟着我重复,“我要这么做即使它很混乱。” 你需要信任我。如果不信任或者致使好奇,前面的FAQ给出了理由。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: