今天一个哥们给我一个毕业设计,说让我重构一下,重新整理一下这个毕业设计。我打开他的源文件一看,是够乱的,首先让我看一下这个源文件吧。我把里边是实现隐藏掉了(隐私)。
以下是 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>;就可以了。所以大家在写模板类的时候一定要注意啊。