"undefined reference to" Ubuntu 上的链接

"undefined reference to" linking on Ubuntu

本文关键字:链接 to undefined reference Ubuntu      更新时间:2023-10-16

我对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。当我在terminal上执行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;
}

如果使用显式实例化,则必须在实例化类之前定义成员函数的泛型版本:

template<class T>
int AdaBoost<T>::readFromFile(char* fName) {
    // ...
}
template class AdaBoost<double>;

然而,如果你没有一个明确的或紧迫的理由来使用显式实例化,那么就使用其他建议,并在头文件中定义模板。

不能在不同的编译单元中分离模板类的定义和实现。换句话说,AdaBoost<T>的完整实现应该链接到与main(使用它的地方)相同的编译单元中。

这通常是固定的#including.cpp文件在你的.hpp文件的末尾(如果你想保持它们分开),或者只是使用.hpp文件实现整个类那里。

你有很多问题。

首先,在CPP文件中使用显式实例化的非常规技术。正如其他人指出的那样,惯例(但仅此而已)要求您将实现放在. h文件中以允许泛型实例化。您不必这样做,但是如果您这样做了,readfile()错误就会消失。(作为替代,将AdaBoost<double>实例化放在AdaBoost::readfile定义的之后。)

接下来,声明了构造函数和析构函数,但没有定义它们。如果希望使用编译器提供的构造函数和析构函数,则应该删除声明。如果你希望使用自己的构造函数和析构函数,你应该定义它们。

最佳实践是去掉AdaBoost.cpp,并修改AdaBoost.h,使其实现内联在头文件中。(注意,这个最佳实践适用于模板化类;其他建议可能适用于非模板化类

您需要将template<class T> int AdaBoost<T>::readFromFile(char* fName)的定义放入AdaBoost.h中,并从构建中删除AdaBoost.cpp

最好将所有模板代码放入头文件中。c++链接器需要消除模板代码的重复实例化,这样你就不会得到"multiply defined symbol"错误。

注:您应该将函数声明为template<class T> int AdaBoost<T>::readFromFile(const char* fName),以消除deprecated conversion from string constant to ‘char*’警告。该函数不需要更改文件名

相关文章: