我对C& C ++并且整整2天都在编译(或者我应该说是链接)。任何人给我一个想法将不胜感激。 错误信息和3个代码文件如下。这些是我从实际工作中减少的最小值,以便你们可以更好地瞥一眼。
环境:Ubuntu 10.10,Eclipse Indigo CDT,g ++(Ubuntu / Linaro 4.4.4-14ubuntu5)4.4.5
错误讯息:
**** Build of configuration Debug for project SceneRec2 ****
make all
Building file: ../src/AdaBoost.cpp
Invoking: GCC C++ Compiler
g++ -I"/home/ubuntuLove/Documents/workspace_eclipse/SceneRec2/Includes" -I/usr/src/linux-headers-2.6.35-30/arch/um/include/shared -O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"src/AdaBoost.d" -MT"src/AdaBoost.d" -o "src/AdaBoost.o" "../src/AdaBoost.cpp"
Finished building: ../src/AdaBoost.cpp
Building file: ../src/AdaMain.cpp
Invoking: GCC C++ Compiler
g++ -I"/home/ubuntuLove/Documents/workspace_eclipse/SceneRec2/Includes" -I/usr/src/linux-headers-2.6.35-30/arch/um/include/shared -O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"src/AdaMain.d" -MT"src/AdaMain.d" -o "src/AdaMain.o" "../src/AdaMain.cpp"
../src/AdaMain.cpp: In function ‘int main(int, char**)’:
../src/AdaMain.cpp:6: warning: deprecated conversion from string constant to ‘char*’
Finished building: ../src/AdaMain.cpp
Building target: SceneRec2
Invoking: GCC C++ Linker
g++ -o "SceneRec2" ./src/AdaBoost.o ./src/AdaMain.o
./src/AdaMain.o: In function `main':
/home/ubuntuLove/Documents/workspace_eclipse/SceneRec2/Debug/../src/AdaMain.cpp:5: undefined reference to `AdaBoost<double>::AdaBoost()'
/home/ubuntuLove/Documents/workspace_eclipse/SceneRec2/Debug/../src/AdaMain.cpp:6: undefined reference to `AdaBoost<double>::readFromFile(char*)'
/home/ubuntuLove/Documents/workspace_eclipse/SceneRec2/Debug/../src/AdaMain.cpp:8: undefined reference to `AdaBoost<double>::~AdaBoost()'
/home/ubuntuLove/Documents/workspace_eclipse/SceneRec2/Debug/../src/AdaMain.cpp:8: undefined reference to `AdaBoost<double>::~AdaBoost()'
collect2: ld returned 1 exit status
make: *** [SceneRec2] Error 1
**** Build Finished ****
请注意-1。当我在终端上执行g ++时,我收到相同的结果。
请注意-2。链接器参数中.o文件的路径应该是正确的(./src / ###。o)。
AdaBoost.h
#ifndef _ADABOOST_H
#define _ADABOOST_H
#include <iostream>
const double eps = 2.2204e-16;
template<class T>
class AdaBoost
{
int N; //Number of Instances
int D; //Number of Dimensions
int nL; //Number of Learners / Classifiers / Rules
T** fVectors;
int* labels;
void learnRule(int t, double* dist);
double genRule(int t, int* L, double* dist);
public:
//Default Constructor
AdaBoost();
//Constructor
AdaBoost(T** data, int* labels, int n, int d, int nL);
//Train function
void train();
//Test function
void test(double** data, double* pMap);
void test(double** data, double* pMap, int n);
int writeToFile(char* fName);
int readFromFile(char* fName);
//Destructor
~AdaBoost();
};
#endif
AdaBoost.cpp
#include "AdaBoost.h"
#include <fstream>
using namespace std;
template class AdaBoost<double> ;
template<class T>
int AdaBoost<T>::readFromFile(char* fName) {
ifstream inFile;
int temp;
int d, dir;
float thr, wt;
inFile.open(fName);
if (!inFile)
return 0;
inFile >> temp;
this->nL = temp;
int k = 0;
while (!inFile.eof() && k < nL) {
inFile >> d;
inFile >> thr;
inFile >> dir;
inFile >> wt;
k++;
}
inFile.close();
return 1;
}
AdaMain.cpp
#include "AdaBoost.h"
using namespace std;
int main(int argc, char** argv)
{
AdaBoost<double> rdClass;
rdClass.readFromFile("Naerer");
return 0;
}
答案 0 :(得分:2)
如果使用显式实例化,则必须在实例化类之前定义成员函数的通用版本:
template<class T>
int AdaBoost<T>::readFromFile(char* fName) {
// ...
}
template class AdaBoost<double>;
但是,如果您没有特定或紧迫的理由首先使用显式实例化,请使用其他建议并在标题中定义模板。
答案 1 :(得分:1)
您需要将template<class T>
int AdaBoost<T>::readFromFile(char* fName)
的定义放入AdaBoost.h
,然后从您的版本中删除AdaBoost.cpp
。
最好将所有模板代码放入标题中。 C ++链接器需要消除模板代码的重复实例化,因此您不会得到“多重定义的符号”错误。
P.S。您应该将函数声明为template<class T>
int AdaBoost<T>::readFromFile(const char* fName)
以消除deprecated conversion from string constant to ‘char*’
警告。该函数不需要更改文件名。
答案 2 :(得分:1)
您不能在不同的编译单元中分隔模板类定义和实现。换句话说,AdaBoost<T>
完整实现应该在main
(使用它的地方)的同一编译单元中链接。
这通常由#including
.cpp
文件末尾的.hpp
文件修复(如果您想将它们分开保存),或者只使用{{1在那里实现整个类的文件。
答案 3 :(得分:1)
你有很多问题。
首先,您在CPP文件中使用非常规的显式实例化技术。正如其他人所指出的那样,约定(但仅此而已)要求您将实现放在.H文件中以允许进行泛型实例化。您不必这样做,但如果您这样做,readfile()错误将消失。 (作为替代方案,请将AdaBoost<double>
实例化放在 AdaBoost::readfile
的定义之后。)
接下来,您已声明但未定义构造函数和析构函数。如果您希望使用编译器提供的构造函数和析构函数,则应删除声明。如果您希望使用自己的构造函数和dstructor,则应该定义它们。
最佳做法是删除AdaBoost.cpp,并修改AdaBoost.h以在头文件中包含内联实现。 (请注意,此最佳实践适用于模板化类;其他建议可能适用于非模板化类。)