加入收藏 | 设为首页 | 会员中心 | 我要投稿 云计算网_泰州站长网 (http://www.0523zz.com/)- 视觉智能、AI应用、CDN、行业物联网、智能数字人!
当前位置: 首页 > 站长学院 > PHP教程 > 正文

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

发布时间:2021-12-13 12:31:18 所属栏目:PHP教程 来源:互联网
导读:今天看到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:

今天看到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 2008ProjectsAcceleratedDebugAccelerated.exe : fatal error LNK1120: 5 个无法解析的外部命令
1>生成日志保存在“file://e:360data重要数据我的文档Visual Studio 2008ProjectsAcceleratedAcceleratedDebugBuildLog.htm”
1>Accelerated - 6 个错误,0 个警告
========== 生成: 成功 0 个,失败 1 个,最新 0 个,跳过 0 个 ==========
 
上面问题不知道怎么解决,就开始google解决方案: 模板不支持分离编译, 把你模板类的声明和实现放到.h文件里面 。按照这个说的把.h和.cpp文件合并后,果然可以了。

(编辑:云计算网_泰州站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    热点阅读