博主在学习数据结构(C++版,邓俊辉)时,发现敲打书上代码报错,其错误类型是error LNK2019以及error C2244:第一个错误表示:使用了无法解析的外部符号,说明定义和声明没有衔接上,所以=和[]操作符重载失败,因为我是类模板的定义和成员函数定义分别放在h和cpp文件中的,我将报错的函数定义直接移到头文件中,暂时解决了第一个错误。而第二个错误表示:无法将函数定义与现有的声明匹配,但是我仔细检查了定义和匹配是一模一样的,而且我在头文件中是用了#ifndef和#define来防止头文件被重复包含。
博主仔细思考后,感觉是跟模板类的编写规则有关,就回去查阅了c++ primer 讲模板类的部分。发现这个错误是与模板编译类型有关!模板编译类型分为:“包含”模型和“分别编译”模型。因为博主所用的编译器是VS2012,只支持包含模型,重点介绍包含模型来解决上面的问题。解决方案:在类模板的头文件定义类结束后加上#include “模板类名.cpp”,例如:
解决方案1:
// header file Vector.h
#ifndef VECTOR_H
#define VECTOR_H
template <class T> class Vector{
//成员和成员函数声明或定义
};
#include "Vector.cpp" //包含在头文件中只声明的成员函数的定义,一定记得加!
#endif
若只是这样,你可能仍然会报错:重复定义或声明某个函数,你还需要做这样的操作:
// Vector.cpp
#ifndef VECTOR_CPP
#define VECTOR_CPP
...//定义那些成员函数
#endif
这样解决重复定义问题,你的程序可以重新运行了!
“分别编译”模型:
一句话:就是在cpp文件一开始加上export templateclass 你的类名然后再#include “你的模板类名.h” 成员函数定义…;由于VS2012貌似不支持,所以我也无法演示和验证该方法能否解决问题。。
注意:包含模型的解决方法不适于特化函数和模板函数都放在cpp文件中定义的情况,这种情况下两种办法:1.在特化函数定义加上inline ,将其声明为内联函数。2.使用笨方法,将模板函数定义放于头文件定义中,将特化函数定义放于cpp文件中,具体可参考这篇博客,讲解很详细 。
http://blog.csdn.net/lh844386434/article/details/6713361 。
第一次写博客,不足之处还请指导和见谅!大家觉得有用的请点个赞~
附我的例子代码参考(源于数据结构(C++语言版)第三版):
// Vector.h
#ifndef VECTOR_H_
#define VECTOR_H_
typedef int Rank;
#define DEFAULT_CAPACITY 3
template <typename T> class Vector{
protected :
Rank _size; int _capacity; T* _elem;
void copyFrom(T const* A,Rank lo,Rank hi);
void expand();
void shrink();
bool bubble(Rank lo,Rank hi);
void bubbleSort(Rank lo,Rank hi);
Rank max(Rank lo,Rank hi);
void selectionSort(Rank lo,Rank hi);
void merge(Rank lo,Rank mi,Rank hi);
void mergeSort(Rank lo,Rank hi);
Rank partition(Rank lo,Rank hi);
void quickSort(Rank lo,Rank hi);
void heapSort(Rank lo, Rank hi);
public:
//构造函数
Vector(int c = DEFAULT_CAPACITY, int s=0,T v=0)
{
_elem= new T[_capacity=c];
for (_size=0;_size<s;_elem[_size++]=v);
}
Vector (T const* A,Rank n){
copyFrom(A,0,n);
}
Vector (T const* A,Rank lo,Rank hi){
copyFrom(A,lo,hi);
}
Vector (Vector<T> const& V){
copyFrom(V._elem,0,V._size);
}
Vector (Vector<T> const& V,Rank lo,Rank hi){
copyFrom(V._elem,lo,hi);
}
//析构函数
~Vector()
{
delete [] _elem;
}
// 只读访问接口
Rank size() const
{
return _size;
}
bool empty() const{
return _size;
}
int disordered() const;
Rank find (T const& e) const{
return find(e,0,_size);
}
Rank find(T const& e,Rank lo,Rank hi ) const;
Rank search(T const& e) const{
return (0>=_size)?-1:search(e,0,_size);
}
Rank search(T const& e,Rank lo,Rank hi) const;
//可写访问接口
T& operator[](Rank r) const;
Vector<T> & operator=(Vector<T> const&);
T remove(Rank r);
int remove(Rank lo,Rank hi);
Rank insert(Rank r,T const& e);
Rank insert(T const& e){
return insert(_size,e);
}
void sort(Rank lo,Rank hi);
void sort(){
sort(0,_size);
}
void unsort(Rank lo,Rank hi);
void unsort(){
unsort(0,_size);
}
int deduplicate();
int uniquify();
//遍历
void traverse(void(*) (T&));
template<typename VST> void traverse(VST&);
};
#include "Vector.cpp"
#endif
// Vector.cpp
#ifndef VECTOR_C_
#define VECTOR_C_
#include "Vector.h"
template <typename T> void Vector<T>::copyFrom(T const* A,Rank lo,Rank hi){
_elem=new T[_capacity=2*(hi-lo)];
_size=0;
while(lo<hi)
_elem[_size++] = A[lo++];
}
template <typename T> Vector<T>& Vector<T>::operator=(Vector<T> const& V){
if (_elem)
delete [] _elem;
copyFrom(V._elem,0,V.size());
return *this;
}
template <typename T>void Vector<T>::expand()
{
if (_size< _capacity) return;
if (_capacity < DEFAULT_CAPACITY)
_capacity=DEFAULT_CAPACITY;
T* oldElem= _elem; _elem= new T[_capacity<<1];
for (int i=0;i<_size;i++)
_elem[i]=oldElem[i];
delete [] oldElem;
}
template <typename T> void Vector<T>::shrink()
{
if (_capacity<DEFAULT_CAPACITY <<1) return;
if (_size <<2 > _capacity) return;
T* oleElem=_elem; _elem=new T[_capacity >>1];
for (int i=0;i<_size;i++)
_elem[i]=oleElem[i];
delete [] oleElem;
}
template <typename T> T& Vector<T>::operator[] (Rank r) const
{
return _elem[r];
}
template <typename T> void permute(Vector<T>& V)
{
for (int i=V.size();i>0;i--)
swap(V[i-1],V[rand() % i]);
}
template <typename T> void Vector<T>::unsort(Rank lo,Rank hi){
T* V=_elem+lo;
for (Rank i=hi-lo;i>0;i--)
swap(V[i-1],V[rand() % i]);
}
template <typename T> static bool lt(T* a,T* b){ return lt(*a,*b);}
template <typename T> static bool lt(T& a,T& b){ return a<b;}
template <typename T> static bool eq(T* a,T* b){ return eq(*a,*b);}
template <typename T> static bool eq(T& a,T& b){ return a==b;}
template <typename T>
Rank Vector<T>::find(T const& e,Rank lo,Rank hi) const{
while ((lo<hi--) && (e!=_elem[hi])); //(0,n),首先执行lo<hi--,则hi=n-1,_elem[hi]正确;当hi=1时,执行完e!=_elem[0]后还是执行一次lo<hi--,则hi=lo-1!
return hi;
}
template <typename T>
Rank Vector<T>::insert (Rank r, T const& e){
expand();
for (int i=_size;i>r;i--)
_elem[i]=_elem[i-1];
_elem[r]=e;
_size++;
return r;
}
template <typename T> int Vector<T>::remove(Rank lo,Rank hi){
if (lo==hi) return 0;
while (hi<_size) _elem[lo++]=_elem[hi++];
_size=lo;
shrink();
return hi-lo;
}
template <typename T> T Vector<T>::remove(Rank r){
T e=_elem[r];
remove(r,r+1);
return e;
}
template <typename T> int Vector<T>::deduplicate(){
int oldsize=_size;
Rank i=1;
while (i<_size)
(find(_elem[i],o,i))<0? i++ :remove(i);
return oldsize-_size;
}
template <typename T> void Vector<T>::traverse (void (*visit) (T&))
{
for (int i=0;i<_size;i++)
visit(_elem[i]);
}
template <typename T> template <typename VST>
void Vector<T>::traverse(VST &visit)
{
for (int i=0;i<_size;i++)
visit(_elem[i]);
}
template <typename T> struct Increase
{
virtual void operator() (T& e){
e++;
}
};
template <typename T> void increase (Vector<T> &V)
{
V.traverse(Increase<T>());
}
template <typename T> int Vector<T>::disordered() const{
int n=0;
for (int i=1;i<_size;i++)
if (_elem[i-1]>_elem[i]) n++;
return n;
} //n=0有序
template <typename T> int Vector<T>::uniquify() { //有序向量重复元素剔除算法(高效版)
Rank i=0,j=0;
while(++j<_size)
if (_elem[i]!=_elem[j])
{
_elem[++i]=_elem[j];
}
_size=++i;
shrink();
return j-i;
}
//有序查找为search()
//template <typename T> static Rank binSearch(T *A,T const& e,Rank lo,Rank hi){ //版本A
// while (lo<hi){
// Rank mi=(lo+hi)>>1;
// if (e<A[mi])
// hi=mi;
// else if (e>A[mi])
// lo=mi;
// else
// return mi;
// }
// return -1;
//}
//template <typename T> static Rank binSearch(T* A,T cosnt& e,Rank lo,Rank hi){ //版本B
// while (1<hi-lo){
// Rank mi=(lo+hi)>>1;
// (e<A[mi])?hi=mi:lo=mi;
// }
// return (e==A[lo])?lo:-1;
//}
template <typename T> static Rank binSearch(T* A,T const& e,Rank lo,Rank hi){ //版本C,返回小于等于e的秩最大者
while (lo<hi){
Rank mi=(lo+hi)>>1;
(e<A[mi])?hi=mi:lo=mi+1;
}
return --lo;
}
#include "Fib.h" //自己编写Fib.h
template <typename T> static Rank fibSearch(T* A,T const& e,Rank lo,Rank hi){
Fib fib(hi-lo);
while (lo<hi){
while (hi-lo<fib.get()) fib.prev();
Rank mi=lo+fib.get()-1;
if (e<A[mi]) hi=mi;
else if (e>A[mi]) lo=mi;
else
return mi;
}
return -1;
}
template <typename T>
Rank Vector<T>::search(T const& e,Rank lo,Rank hi) const{
return (rand() % 2)? binSearch(_elem,e,lo,hi):fibSearch(_elem,e,lo,hi);
}
template <typename T> void Vector<T>::sort (Rank lo,Rank hi){
switch (rand()%5)
{
case 1:
case 2:bubbleSort(lo,hi);break;
case 3:
case 4:mergeSort(lo,hi);break;
default:
mergeSort(lo,hi);break;
break;
}
}
template<typename T> bool Vector<T>::bubble(Rank lo,Rank hi){
bool sorted=true;
while(++lo<hi)
{
if (_elem[lo-1]>_elem[lo]){
sorted=false;
swap(_elem[lo-1],_elem[lo]);
}
}
return sorted;
}
template <typename T> void Vector<T>::bubbleSort(Rank lo,Rank hi)
{
while(!bubble(lo,hi--)) ;
}
template<typename T> void Vector<T>::merge(Rank lo,Rank mi,Rank hi){
T* A=_elem+lo;
int lb=mi-lo;
T *B=new T[lb];
for (Rank i=0;i<lb;B[i]=A[i++]);
int lc=hi-mi; T* C=_elem+mi;
for (Rank i=0,j=0,k=0;(j<lb) ||(k<lc);){
if ((j<lb) && (!(k<lc) || B[j]<=C[k])) A[i++] =B[j++];
if ((k<lc) && (!(j<lb) || C[k]<B[j])) A[i++]=C[k++];
}
delete [] B;
}
template <typename T> void Vector<T>::mergeSort(Rank lo,Rank hi){
if (hi-lo <2) return;
int mi=(hi+lo)/2;
mergeSort(lo,mi);
mergeSort(mi,hi);
merge(lo,mi,hi);
}
#endif
// main.cpp 测试Vector部分功能
#include <iostream>
#include "Vector.h"
#include "Fib.h"
using namespace std;
int main(int argc,char* argv[])
{
const int a[]={1,3,4,7,2,5,9,6,8};
Vector<int> v1(a,9),v2;
v2=v1;
cout<<"v1: ";
permute(v1);
for (int i=0;i<v1.size();i++)
cout<<v1[i]<<" ";
cout<<endl;
cout<<"v2: ";
for (int i=0;i<v2.size();i++)
cout<<v2[i]<<" ";
cout<<endl;
int flag=v2.find(5,0,9);
cout<<flag<<endl;
v2.insert(4,10);
cout<<"v2: ";
for (int i=0;i<v2.size();i++)
cout<<v2[i]<<" ";
cout<<endl;
v2.remove(4,5);
cout<<"v2: ";
for (int i=0;i<v2.size();i++)
cout<<v2[i]<<" ";
cout<<endl;
v1.sort(0,9);
cout<<"v1: ";
for (int i=0;i<v1.size();i++)
cout<<v1[i]<<" ";
cout<<endl;
return 0;
}