C++模板函数声明定义分离编译错误详解

今天看到accelerated c++上有个简单的vector容器的实现Vec,就再vs2008上编译了下:

/////  Vec.h

#ifndef GUARD_VEC_H

#define GUARD_VEC_H

#include <iostream>

#include <iterator>

#include <memory>

//#include <xmemory>

template <class T>

class Vec

{

public:

typedef T* iterator;

typedef const T* const_iterator;

typedef size_t size_type;

typedef T value_type;

typedef T& reference;

typedef const T& const_reference;

Vec() {create();} //默认的构造函数

explicit Vec(size_type n,const T& t=t()) {create(n,t);} //单参数或者两个参数构造函数

Vec(const Vec& v) {create(v.begin(),v.end());} //拷贝构造函数

Vec& operator=(const Vec&);  //赋值构造函数

~Vec() {uncreate();} //析构函数

size_type size() { return avail-data; } //定义类的大小,ptrdiff_t自动转化成size_t

void push_back(const T& t)

{

if (avail==limit)

{

grow();

}

unchecked_append(t);

}

//重载【】

T& operator[] (size_type i) { return data[i]; }

const T& operator[] (size_type i) const { return data[i]; }

//定义begin和end,都有两个版本

iterator begin() {return data;}

const_iterator begin() const {return data;}

iterator end() {return avail;}

const_iterator end() const {return avail;}

protected:

private:

iterator data; //Vec中得初始值

iterator avail; //Vec中得结束值

iterator limit; //Vec中空间分配的结束值

std::allocator<T> alloc; //注意此处std

//创造函数,负责内存管理

void create();

void create(size_type,const T&);

void create(const_iterator,const_iterator);

//销毁元素,返回内存

void uncreate();

//支持push_back函数

void grow();

void unchecked_append(const T&);

};

#endif


////  Vec.cpp

#include <iostream>

#include "Vec.h"

//#pragma comment(lib,"ws2_32.lib")

using namespace std;

//拷贝构造函数

template <class T>

Vec<T>& Vec<T>::operator=(const Vec& v)

{

if (&v!=this) //检查是否为自我赋值,很重要,必须有

{

uncreate(); //清空左值的元素

create(v.begin(),v.end()); //拷贝元素到左值

}

return *this;

}

//push_back函数中内存增长策略函数

template <class T>

void Vec<T>::grow()

{

size_type new_size=max(2*(limit-data),ptrdiff_t(1)); //防止刚开始内存空间为0的情况

iterator new_data=alloc.allocate(new_size); //返回首地址

//把前两个参数指定的元素复制给第三个参数表示的目标序列,返回末尾元素的下一个迭代器

iterator new_avail=uninitialized_copy(data,avail,new_data);

uncreate(); //释放原先的空间

data=new_data;

avail=new_avail;

limit=data+new_size;

}

//向申请的内存中添加元素

template <class T>

void Vec<T>::unchecked_append(const T& val)

{

//在未初始化的空间构建一个对象,参数1插入对象的位置指针,参数2需要添加的对象

alloc.construct(avail++,val);

}

//申请内存的函数create

template <class T>

void Vec<T>::create()

{

data=avail=limit=0;

}

template <class T>

void Vec<T>::create(size_type n,const T& val)

{

data=alloc.allocate(n); //申请内存空间,但是不初始化

limit=avail=data+n;

uninitialized_fill(data,limit,val); //进行初始化

}

template <class T>

void Vec<T>::create(const_iterator i,const_iterator j)

{

data=alloc.allocate(j-i);

limit=avail=uninitialized_copy(i,j,data);

}

//回收内存

template <class T>

void Vec<T>::uncreate()

{

if (data) //如果data是0,我们不需要做什么工作

{

iterator it=avail;

while (it!=data)

alloc.destroy(--it); //销毁没个元素,为了与delete行为一致,采用从后向前遍历

alloc.deallocate(data,limit-data); //内存释放,函数需要一个非零指针

//因此,检测data是否为零

}

data=limit=avail=0;

}


//// 测试的main函数

#include <iostream>

#include "Vec.h"

using namespace std;

int main()

{

Vec<int> a;

Vec<int> b;

a.push_back(12);

b=a;

return 0;


 
结果编译后出现下面错误:
 
1>------ 已启动生成: 项目: Accelerated, 配置: Debug Win32 ------
1>正在编译...
1>Vec.cpp
1>Vec_example.cpp
1>正在生成代码...
1>正在链接...
1>Vec_example.obj : error LNK2001: 无法解析的外部符号 "public: class Vec<int> & __thiscall Vec<int>::operator=(class Vec<int> const &)" (??4?$Vec@H@@QAEAAV0@ABV0@@Z)
1>Vec_example.obj : error LNK2001: 无法解析的外部符号 "private: void __thiscall Vec<int>::create(void)" (?create@?$Vec@H@@AAEXXZ)
1>Vec_example.obj : error LNK2001: 无法解析的外部符号 "private: void __thiscall Vec<int>::uncreate(void)" (?uncreate@?$Vec@H@@AAEXXZ)
1>Vec_example.obj : error LNK2001: 无法解析的外部符号 "private: void __thiscall Vec<int>::unchecked_append(int const &)" (?unchecked_append@?$Vec@H@@AAEXABH@Z)
1>Vec_example.obj : error LNK2001: 无法解析的外部符号 "private: void __thiscall Vec<int>::grow(void)" (?grow@?$Vec@H@@AAEXXZ)
1>E:\360data\重要数据\我的文档\Visual Studio 2008\Projects\Accelerated\Debug\Accelerated.exe : fatal error LNK1120: 5 个无法解析的外部命令
1>生成日志保存在“file://e:\360data\重要数据\我的文档\Visual Studio 2008\Projects\Accelerated\Accelerated\Debug\BuildLog.htm”
1>Accelerated - 6 个错误,0 个警告
========== 生成: 成功 0 个,失败 1 个,最新 0 个,跳过 0 个 ==========
 
上面问题不知道怎么解决,就开始google解决方案: 模板不支持分离编译, 把你模板类的声明和实现放到.h文件里面 。按照这个说的把.h和.cpp文件合并后,果然可以了。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/ad7a595ee7537bda476a17e8522a7e6a.html