“在Ubuntu上链接的未定义引用”

时间:2011-07-12 22:52:16

标签: c++ linker

我对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;
}

4 个答案:

答案 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以在头文件中包含内联实现。 (请注意,此最佳实践适用于模板化类;其他建议可能适用于非模板化类。)

相关问题