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文件合并后,果然可以了。

  • 1
  • 2
  • 下一页

相关内容

    暂无相关文章