编写模板类时注意一点 2007-12-06 11:22

今天一个哥们给我一个毕业设计,说让我重构一下,重新整理一下这个毕业设计。我打开他的源文件一看,是够乱的,首先让我看一下这个源文件吧。我把里边是实现隐藏掉了(隐私)。

以下是 TestSJK.cpp文件的内容

//****************************begin********************************************

#include <iostream>
#include <fstream>
#include <string>
#include <iomanip>
using namespace std;
const int MaxSize=100;
struct  Voter
{
 string VoterName ;
 string VoterSex;
 string VoterAge;
 string VoterNativeplace;
 string Bestman;
};   //选举人
struct Candidate//候选人
{
 string   CandidateName;
 string   CandidateSex;
 int      CandidateAge;
 int      count;
} Cdt[3];
template < class T >
class Operation
{
public:
 Operation  () {length=0;}
 Operation (T Entire[],int n);
 ~Operation () {}
 void Insert (int i,T x);     //插入选举人的函数
 void Delete (int i);         //删除选举人的函数
 void display();              //显示候选人所得选票的结果
 void printall();             //在显示器上输出所有选举人的信息
 void CurrentDataStorage();   //对输入的数据进行保存
 void CandidateResume();      //查看候选人的简历
    //void InitializeCandidate();
private:
 T Voterinfo[MaxSize];        //存放选举人信息的数组(顺序表)
 int length;
};
//将数组信息转化为顺序表的信息
template <class T >
Operation <T>:: Operation (T Entire[ ], int n)
{

.  .  .   .   .   .     .
 }
// 插入函数Insert,将x插入到登记表第i个位置
template <class T >
void Operation <T>::Insert(int i, T x)
{
 .  .  .   .   .   .     .

}
//删除函数,删除序号为i 的元素
template <class T >
void Operation <T>::Delete(int i)
{
 .  .  .   .   .   .     .

}
//显示候选人所得选票的结果的函数
template <class T >
void Operation <T>::display()
{
 .  .  .   .   .   .     .

}
template <class T >
void Operation <T>::CandidateResume()
{
 .  .  .   .   .   .     .

}

//对输入的数据进行文件保存
template <class T >
void Operation <T>::CurrentDataStorage()
{
    .  .  .   .   .   .     .

}
void show_value()
{
    .  .  .   .   .   .     .

}
int main()

    .  .  .   .   .   .     .

 } 
 //****************************************end*****************************************

首先说一下这个cpp文件不拖的地方,第一,看内容的话不知道这个程序是c还是c++,根据现象来说应该是一个c程序。可里边用到了面向对象的类这个概念,很让人疑惑;第二风格问题,一会是c++定义,一会是c函数定义,看起来是一团糟;第三命名规则问题,命名不规范,我只能说我不懂他的意思;第四业务逻辑关系,条理不清晰。以上问题我在重构时都已经解决了。但是碰到一个模板类定义的问题,想必所有学过泛型编程(STL)的都会碰到但没有尝试过去如何修改。

先看看我重构后的代码吧。

//**********************************begin********************************************

首先我定义了一个头文件存放公共信息的commn.h文件,内容如下

#include <iostream>
#include <fstream>
#include <string>
#include <iomanip>

using namespace std;

const int MaxSize=100;

typedef struct _Voter
{

 .  .  .   .   .   .     .
}Voter;   //选举人

typedef struct _Candidate//候选人
{
  .  .  .   .   .   .     .

} Candidate;

我又定义了一个选择操作类声明文件,Operation.h文件内容如下

#include "commn.h"

#ifndef OPERATION_H
#define OPERATION_H

template < class T >
class Operation
{
public:
 Operation  ();
 Operation (T Entire[],int n);
 ~Operation () ;
 void Insert (int i,T x);     //插入选举人的函数
 void Delete (int i);         //删除选举人的函数
 void display();              //显示候选人所得选票的结果
 void printall();             //在显示器上输出所有选举人的信息
 void CurrentDataStorage();   //对输入的数据进行保存
 void CandidateResume();      //查看候选人的简历
 void show_value();           //显示的操作 
    //void InitializeCandidate();
private:
 T Voterinfo[MaxSize];        //存放选举人信息的数组(顺序表)
 int length;
};

#endif

接着我定义了选举操作的类,Operation.cpp文件,文件如下

#include "TestSJKB.h"

template <class T >
Operation <T>::Operation()
{
  .  .  .   .   .   .     .
}

template <class T >
Operation <T>::~Operation()
{
}

//using namespace std;
//将数组信息转化为顺序表的信息
template <class T >
Operation <T>:: Operation (T Entire[ ], int n)
{
 .  .  .   .   .   .     .

}

// 插入函数Insert,将x插入到登记表第i个位置
template <class T >
void Operation <T>::Insert(int i, T x)
{
  .  .  .   .   .   .     .

}

//删除函数,删除序号为i 的元素
template <class T >
void Operation <T>::Delete(int i)
{
  .  .  .   .   .   .     .

}

//显示候选人所得选票的结果的函数
template <class T >
void Operation <T>::display()
{
  .  .  .   .   .   .     .

}

template <class T >
void Operation <T>::CandidateResume()
{
  .  .  .   .   .   .     .

}

//在显示器上输出所有选举人的信息
template <class T >
void Operation <T>::printall()
{
  .  .  .   .   .   .     .

}

//对输入的数据进行文件保存
template <class T >
void Operation <T>::CurrentDataStorage()
{
    .  .  .   .   .   .     .

}

template <class T>
void Operation <T>::show_value()
{
      .  .  .   .   .   .     .

}

这是我的测试文件

#include "TestSJKB.h"

int main()

    .   .    .    .     .     .

 }

//************************************end****************************

在编译连接时出现了

testmain.obj : error LNK2019: 无法解析的外部符号 "public: __thiscall Operation<struct _Voter>::~Operation<struct _Voter>(void)" (??1?$Operation@U_Voter@@@@QAE@XZ),该符号在函数 __catch$_main$0 中被引用
testmain.obj : error LNK2019: 无法解析的外部符号 "public: void __thiscall Operation<struct _Voter>::CurrentDataStorage(void)" (?CurrentDataStorage@?$Operation@U_Voter@@@@QAEXXZ),该符号在函数 __catch$_main$0 中被引用
testmain.obj : error LNK2019: 无法解析的外部符号 "public: void __thiscall Operation<struct _Voter>::printall(void)" (?printall@?$Operation@U_Voter@@@@QAEXXZ),该符号在函数 __catch$_main$0 中被引用
testmain.obj : error LNK2019: 无法解析的外部符号 "public: void __thiscall Operation<struct _Voter>::display(void)" (?display@?$Operation@U_Voter@@@@QAEXXZ),该符号在函数 __catch$_main$0 中被引用
testmain.obj : error LNK2019: 无法解析的外部符号 "public: void __thiscall Operation<struct _Voter>::Delete(int)" (?Delete@?$Operation@U_Voter@@@@QAEXH@Z),该符号在函数 __catch$_main$0 中被引用
testmain.obj : error LNK2019: 无法解析的外部符号 "public: void __thiscall Operation<struct _Voter>::Insert(int,struct _Voter)" (?Insert@?$Operation@U_Voter@@@@QAEXHU_Voter@@@Z),该符号在函数 _main 中被引用
testmain.obj : error LNK2019: 无法解析的外部符号 "public: void __thiscall Operation<struct _Voter>::CandidateResume(void)" (?CandidateResume@?$Operation@U_Voter@@@@QAEXXZ),该符号在函数 _main 中被引用
testmain.obj : error LNK2019: 无法解析的外部符号 "public: void __thiscall Operation<struct _Voter>::show_value(void)" (?show_value@?$Operation@U_Voter@@@@QAEXXZ),该符号在函数 _main 中被引用
testmain.obj : error LNK2019: 无法解析的外部符号 "public: __thiscall Operation<struct _Voter>::Operation<struct _Voter>(void)" (??0?$Operation@U_Voter@@@@QAE@XZ),该符号在函数 _main 中被引用
.\Debug/TestSJKB.exe : fatal error LNK1120: 9 个无法解析的外部命令

等错误为什么呢?这就是我要讲述的问题所在。模板在没有实例化之前是无法编译的,因为没有使用类型实例化的模板是不能生成代码的。所以一般处理模板的方法是,将模板的声明和定义都放到一个.h文件之中,或者使用export关键字,但是后者在很多C++编译器实现(如:VC)中不被支持.如果说硬要把声明和定义分开来写的,像我这样用也是可以的,不过用起来就不方便会出现像上面类似的错误!像上面一样产生错误的原因就是因为没有使用类型实例化,呵呵所有在使用模板类的时候一定要在定义文件里类型实例化哦。如何类型实例化?在我们的定义文件里声明一下既可,我在定义的Operation.cpp文件里声明如下: template class Operation<Voter>;就可以了。所以大家在写模板类的时候一定要注意啊。

猜你喜欢

转载自www.cnblogs.com/lu-ping-yin/p/10988675.html
今日推荐