最近这两天在做一个C++的小项目,主要用于文本的分析。用MFC完成,基于Dialog实现,在原来的基础上加入了一个myThreadPool类。在CLogsReaderDlg这个类中实现一个文件扫描线程,通过myThreadPool类实现一个线程池进行文本的分析。两者通过一个queue进行通信(存放扫描线程压入的文件名)。类结构如下:
先完成了各个模块 ,最后在链接各个模块时却出现了一个重复定义:error lnk2005!不多说先上代码:这个是myThreadPool类:
在CLogsReaderDlg类中进行调用:
链接时却出现了错误:
Linking...
LogsReaderDlg.obj : error LNK2005: "public: __thiscall ThreadPool::ThreadPool(void)" (??0ThreadPool@@QAE@XZ) already defined in LogsReader.obj
LogsReaderDlg.obj : error LNK2005: "public: int __thiscall ThreadPool::InitializeThreadPool(int)" (?InitializeThreadPool@ThreadPool@@QAEHH@Z) already defined in LogsReader.obj
LogsReaderDlg.obj : error LNK2005: "public: void __thiscall ThreadPool::DestroyThreadPool(void)" (?DestroyThreadPool@ThreadPool@@QAEXXZ) already defined in LogsReader.obj
LogsReaderDlg.obj : error LNK2005: "public: int __thiscall ThreadPool::PostWorkItem(class CString *)" (?PostWorkItem@ThreadPool@@QAEHPAVCString@@@Z) already defined in LogsReader.obj
LogsReaderDlg.obj : error LNK2005: "void __cdecl UserProc1(class CString *,void *)" (?UserProc1@@YAXPAVCString@@PAX@Z) already defined in LogsReader.obj
LogsReaderDlg.obj : error LNK2005: "unsigned long __stdcall WorkerThread(void *)" (?WorkerThread@@YGKPAX@Z) already defined in LogsReader.obj
Debug/LogsReader.exe : fatal error LNK1169: one or more multiply defined symbols found
检查了一个代码,已经使用了:
#ifndef _MY_THREADPOOL_H_
#define _MY_THREADPOOL_H_
//....... ..................
#endif
但为什么还是会出现这样的错误呢?
认真分析一下,C++的只会对*.cpp文件进行处理,*.h文件会在*.cpp文件中打开。在其他文件中只要包含了*.h就会独立的解释,然后每个*.cpp文件生成独立的标示符。在编译器链接时,就会将工程中所有的符号整合在一起,由于文件中有重名变量,于是就出现了重复定义的错误。所以问题出在我将myThreadPool类的声明和实现放在了一个*.h头文件中,于是就出现了在几个文件中重复定义的情况。这个时候我们需要将声明和定义分开。而预处理只能肖除重复包含却不能解决重定义!
关于定义和声明,我们可以将定义看成两种:类型定义、数据定义 。类型定义是会不分配内存的,比如类、结构体的定义,它是定义一个数据类型而已 。而数据定义会分配内存,比如类对象定义,变量定义。根据标准手册:Int a是定义,会分配内存;extern int a是声明,不分配内存。
由此我们可知:不分配内存的,放在*.h文件;分配内存的放在*.cpp文件,放置重复定义。这样问题就解决了!