最近我们数据采集组的采集和存储程序需要一个Stop功能,为了采集端和存储端的代码兼容,我想用C++类模板来写,在用gcc编译类模板的时候出现了问题,跟vs2010下编译方法不同,vs2010下面支持分离式编译(包含编译),但是gcc下不支持,
(1)vs2010下模板编译的3种方法:
1.模板的声明和实现均在一个头文件netKill.h,main.cpp中包含头文件使用类模板:
//netKill.h #ifndef NETKILL_H #define NETKILL_H #include<set> #include<string> #include<sstream> #include<cstdlib> #include<iostream> #include<algorithm> #include<fstream> //#include<pthread.h> template<typename T> class NetKill{ private: std::set<T> ids; std::set<T> hasExitIds; public: void killIds(); void clearIds(); void addId(T pid); void deleteId(T pid);//sig_child void printIds();//for debug }; template<typename T> void NetKill<T>::addId(T id){ std::cout<<"add"<<std::endl; ids.insert(id); } template<typename T> void NetKill<T>::clearIds(){ ids.clear(); hasExitIds.clear(); } template<typename T> void NetKill<T>::deleteId(T id){ hasExitIds.insert(id); } template<typename T> void NetKill<T>::killIds(){ std::ofstream fOut("kill.txt"); if(!fOut)std::cout<<"open file error"<<std::endl; for(std::set<T>::const_iterator cit=ids.begin();cit!=ids.end();cit++){ std::string cmdKill("kill -9 "); std::stringstream strm; strm<<*cit; std::string mid; strm>>mid; cmdKill+=mid; std::set<T>::iterator flag=hasExitIds.find(*cit); if(flag==hasExitIds.end()){ fOut<<cmdKill<<std::endl; std::cout<<cmdKill<<std::endl; //system(cmdKill.c_str()); } }//for fOut.clear(); fOut.close(); clearIds(); } template<typename T> void NetKill<T>::printIds(){//for debug std::ofstream fOut("test.txt"); if(!fOut)std::cout<<"open file error"<<std::endl; for(std::set<T>::const_iterator cit=ids.begin();cit!=ids.end();cit++) fOut<<*cit<<","; fOut<<std::endl; fOut.clear(); fOut.close(); } //#include "netKill.cpp" #endif
//main.cpp #include"netKill.h" #include<cstdlib> int main(int argc,char** argv){ NetKill<int> nk; nk.addId(12034); //nk.deleteId(12034); nk.printIds(); nk.killIds(); return EXIT_SUCCESS; }
2.包含编译,将模板声明放在头文件netKill.h,模板实现放在netKill.cpp,然后在netKill.h头文件中包含netKill.cpp,但是此时不能将netKill.cpp添加到工程中,只是将netKill.cpp文件拷贝到工程的代码目录下,如下图。因为vs2010会将所有工程中cpp文件编译,但是此时netKill.cpp中没包含头文件,如果将netKill.cpp添加进工程的话,会出现找不到类模板定义。
//netKill.h #ifndef NETKILL_H #define NETKILL_H #include<set> //#include<pthread.h> template<typename T> class NetKill{ private: std::set<T> ids; std::set<T> hasExitIds; public: void killIds(); void clearIds(); void addId(T pid); void deleteId(T pid);//sig_child void printIds();//for debug }; #include "netKill.cpp" #endif
//netKill.cpp #include<string> #include<sstream> #include<cstdlib> #include<iostream> #include<algorithm> #include<fstream> template<typename T> void NetKill<T>::addId(T id){ std::cout<<"add"<<std::endl; ids.insert(id); } template<typename T> void NetKill<T>::clearIds(){ ids.clear(); hasExitIds.clear(); } template<typename T> void NetKill<T>::deleteId(T id){ hasExitIds.insert(id); } template<typename T> void NetKill<T>::killIds(){ std::ofstream fOut("kill.txt"); if(!fOut)std::cout<<"open file error"<<std::endl; for(std::set<T>::const_iterator cit=ids.begin();cit!=ids.end();cit++){ std::string cmdKill("kill -9 "); std::stringstream strm; strm<<*cit; std::string mid; strm>>mid; cmdKill+=mid; std::set<T>::iterator flag=hasExitIds.find(*cit); if(flag==hasExitIds.end()){ fOut<<cmdKill<<std::endl; std::cout<<cmdKill<<std::endl; //system(cmdKill.c_str()); } }//for fOut.clear(); fOut.close(); clearIds(); } template<typename T> void NetKill<T>::printIds(){//for debug std::ofstream fOut("test.txt"); if(!fOut)std::cout<<"open file error"<<std::endl; for(std::set<T>::const_iterator cit=ids.begin();cit!=ids.end();cit++) fOut<<*cit<<","; fOut<<std::endl; fOut.clear(); fOut.close(); }3.可以将netKill.cpp放进vs2010的工程中,不过得在netKill.cpp中添加预编译宏并且include netKill.h,netKill.cpp如下,netKill.h和main.cpp同上。
#ifndef NETKILL_CPP #define NETKILL_CPP #include"netKill.h" #include<string> #include<sstream> #include<cstdlib> #include<iostream> #include<algorithm> #include<fstream> template<typename T> void NetKill<T>::addId(T id){ std::cout<<"add"<<std::endl; ids.insert(id); } template<typename T> void NetKill<T>::clearIds(){ ids.clear(); hasExitIds.clear(); } template<typename T> void NetKill<T>::deleteId(T id){ hasExitIds.insert(id); } template<typename T> void NetKill<T>::killIds(){ std::ofstream fOut("kill.txt"); if(!fOut)std::cout<<"open file error"<<std::endl; for(std::set<T>::const_iterator cit=ids.begin();cit!=ids.end();cit++){ std::string cmdKill("kill -9 "); std::stringstream strm; strm<<*cit; std::string mid; strm>>mid; cmdKill+=mid; std::set<T>::iterator flag=hasExitIds.find(*cit); if(flag==hasExitIds.end()){ fOut<<cmdKill<<std::endl; std::cout<<cmdKill<<std::endl; //system(cmdKill.c_str()); } }//for fOut.clear(); fOut.close(); clearIds(); } template<typename T> void NetKill<T>::printIds(){//for debug std::ofstream fOut("test.txt"); if(!fOut)std::cout<<"open file error"<<std::endl; for(std::set<T>::const_iterator cit=ids.begin();cit!=ids.end();cit++) fOut<<*cit<<","; fOut<<std::endl; fOut.clear(); fOut.close(); } #endif(2)linux下gcc4.4.7不支持分离式编译,即需要将类模板的声明和定义均放在netKill.h头文件中, 并且需要将用到类模板的类型形参前面加上typename
#ifndef NETKILL_H #define NETKILL_H #include<set> #include<string> #include<sstream> #include<cstdlib> #include<iostream> #include<algorithm> #include<fstream> //#include<pthread.h> template<typename T> class NetKill{ private: typename std::set<T> ids; typename std::set<T> hasExitIds;//because in function sig_child,need to flag the pid has exit //and if only pids,multithread will affect the iterator in loop public: void killIds(); void clearIds(); void addId(T pid); void deleteId(T pid);//sig_child void printIds();//for debug }; //#include "netKill.cpp" template<typename T> void NetKill<T>::addId(T id){ std::cout<<"add"<<std::endl; ids.insert(id); } template<typename T> void NetKill<T>::clearIds(){ ids.clear(); hasExitIds.clear(); } template<typename T> void NetKill<T>::deleteId(T id){ hasExitIds.insert(id); } template<typename T> void NetKill<T>::killIds(){ std::ofstream fOut("kill.txt"); if(!fOut)std::cout<<"open file error"<<std::endl; for(typename std::set<T>::const_iterator cit=ids.begin();cit!=ids.end();cit++){ std::string cmdKill("kill -9 "); std::stringstream strm; strm<<*cit; std::string mid; strm>>mid; cmdKill+=mid; typename std::set<T>::iterator flag=hasExitIds.find(*cit); if(flag==hasExitIds.end()){ fOut<<cmdKill<<std::endl; std::cout<<cmdKill<<std::endl; //system(cmdKill.c_str()); } }//for fOut.clear(); fOut.close(); clearIds(); } template<typename T> void NetKill<T>::printIds(){//for debug std::ofstream fOut("test.txt"); if(!fOut)std::cout<<"open file error"<<std::endl; for(typename std::set<T>::const_iterator cit=ids.begin();cit!=ids.end();cit++) fOut<<*cit<<","; fOut<<std::endl; fOut.clear(); fOut.close(); } #endif
编译:
[root@2467 workspace]# vim netKill.h [root@2467 workspace]# g++ main.cpp -std=c++0x -o main [root@2467 workspace]# ./main add kill -9 12034