无法解析的外部符号 "public: virtual __thiscall CachedObj<class Qi
定义一个含 operator new 和 operator delete 函数的基类(此类并不实际使用),然后将真正使用的类继承于这个基类,达到优化内存分配的目的。但是代码通不过编译。出错提示:
Main.obj : error LNK2001: 无法解析的外部符号 "public: virtual __thiscall CachedObj<class Qi>::~CachedObj<class Qi>(void)" (??1?$CachedObj@VQi@@@@UAE@XZ)
C:\Documents and Settings\Administrator\桌面\test\Debug\test.exe : fatal error LNK1120: 1 个无法解析的外部命令
/*为你的类实现一个类特定的内存分配器。测量性能的改变,看看到底有多大帮助。*/ #include<iostream> #include<memory> /* 内存分配类:预先分配对象并维护一个未使用对象的自由列表。 当一个对象被释放, 它将放回自由列表,程序退出时才将内存返还给系统*/template<typename T> class CachedObj { public: void* operator new(size_t); void operator delete(void*,size_t); virtual ~CachedObj(); protected: T* next; // 指向下一个可用对象 private: // static 成员管理自由列表。声明为 static,是因为只为所有给定类型的对象维持一个自由列表 static std::allocator<T> alloc_mem; static void add_to_freelist(T*); //将对象加入自由列表(新分配和删除对象时调用) static T* freeStore; // 指向自由列表表头 static const size_t chunk; // 自由列表为空时将分配的对象数目 }; template<typename T> std::allocator<T> CachedObj<T>:: alloc_mem; // 只定义,无需初始化 template<typename T> T* CachedObj<T>::freeStore = 0; // 列表首指针初始化为 0 template<typename T> const size_t CachedObj<T>::chunk = 50; // 每次分配数量初始化为 50 // new 从自由列表返回一个对象。new 应该只被要求建立一个 T, 而不是从 T 派生一个对象 template<typename T> void* CachedObj<T>::operator new(size_t n) { if(n!==sizeof(T)) // 检测请求的尺寸是否正确 throw runtime_error("CachedObj:在 operator new 中错误的对象尺寸"); if(!freeStore) // 如果列表为空 { T* arr=allo_mem.allocate(chunk); // 分配 chunk 个新 T 类型未构造对象 for(size_t i=0;i!=chunk;++i) // 为新分配内存中的每个对象设置 next 指针 add_to_freelist(arr[i]); T *p=freeStore; freeStore=freeStore->CachedObj::next; return p; // T 的构造函数将构造对象的 T 部分 } } // 将对象放入自由列表头部 template<typename T> void CachedObj<T>::add_to_freelist(T *p) { p->CachedObj::next=freeStore; // 下一个可用对象 = 现在的表头 freeStore=p; // 现在的表头 = p } // operator delete template<typename T> void CachedObj<T>::operator delete(void *p,size_t n) { if(p) add_to_freelist(static_cast<T*>(p)); // 将"删除"的对象添加到列表头部并强制类型转换 } /////////////////// 继承 CachedObj 的实际使用对象:围棋类 ///////////////////// class Qi:public CachedObj<Qi> { public: Qi(int kind,int row=0,int col=0,bool d=false):type(kind),x(row),y(col),dead(d){} void run(int,int); // 走棋 int win(Qi &q); // 输赢(赢:1 和:0 输:-1) double get_space(){return space;};// 数目 private: short type; // 棋子类型(黑:0 白:1) short x,y; // 棋子位置 bool dead; // 棋子死活 double space; // 目数 }; void Qi::run(int row,int col) { if(row<19 && row>=0) x=row; else std::cout<<"位置非法"; if(col<19 && col>=0) y=col; else std::cout<<"位置非法"; } int Qi::win(Qi &q) { if(space>q.get_space()) return 1; else if(space==q.get_space()) return 0; else return -1; } int main() { Qi black(0,12,12); system("pause"); return 0; }第14行对虚析构函数进行实现,如virtual ~CachedObj(){};,可以免除链接错误。
delete操作符会调用析构函数,所以有如下几个办法:
1头文件内析构函数可以不写virtual ~CachedObj(); 这样VC++自动会给你生成一个默认析构函数
2把virtual ~CachedObj();实现掉,这行改成virtual ~CachedObj(){}