简体   繁体   English

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

[英]“undefined reference to” linking on Ubuntu

I'm relatively new to C & C++ and stuck at compiling (or should I say linking) for the whole 2 days.我对 C 和 C++ 比较陌生,并且整整 2 天都在编译(或者我应该说是链接)。 Anyone gives me an idea would be appreciated.任何人给我一个想法将不胜感激。 Error message and 3 code files are below.错误信息和 3 个代码文件如下。 These are what I cut down to minimum from I'm actually working on so that you guys can take a better glimpse at.这些是我从实际工作中减少到最低限度的内容,以便你们可以更好地了解。

Env: Ubuntu 10.10, Eclipse Indigo CDT, g++ (Ubuntu/Linaro 4.4.4-14ubuntu5) 4.4.5环境:Ubuntu 10.10,Eclipse Indigo CDT,g++4-14untuaro 4.4.4.4.ub。

Error message:错误信息:

**** 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 ****

Note-1.注1。 I receive the same result when I execute g++ on terminal.当我在终端上执行 g++ 时,我收到了相同的结果。

Note-2.笔记2。 The path of.o files in the argument for linker should be correct (./src/###.o). linker 的参数中的 .o 文件的路径应该是正确的 (./src/###.o)。

AdaBoost.h 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 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 AdaMain.cpp

#include "AdaBoost.h"
using namespace std;
int main(int argc, char** argv)
{
    AdaBoost<double> rdClass;
    rdClass.readFromFile("Naerer");

    return 0;
}

If you are using explicit instantiation, you have to define the generic version of the member function before instantiating the class:如果您使用显式实例化,则必须在实例化 class 之前定义成员 function 的通用版本:

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

template class AdaBoost<double>;

However, if you don't have a specific or pressing reason to use explicit instantiation in the first place, go with the other recommendations and define the templates in the header.但是,如果您没有特定或紧迫的理由首先使用显式实例化,go 和其他建议并在 header 中定义模板。

You need to put the definition of template<class T> int AdaBoost<T>::readFromFile(char* fName) into AdaBoost.h , and remove AdaBoost.cpp from your build.您需要将template<class T> int AdaBoost<T>::readFromFile(char* fName)的定义放入AdaBoost.h中,并从构建中删除AdaBoost.cpp

It's best to put all template code into the header.最好将所有模板代码放入 header 中。 C++ linkers are required to eliminate duplicate instantiations of template code so you won't get "multiply defined symbol" errors.需要 C++ 链接器来消除模板代码的重复实例化,这样您就不会出现“多重定义符号”错误。

PS You should declare the function as template<class T> int AdaBoost<T>::readFromFile(const char* fName) to get rid of the deprecated conversion from string constant to 'char*' warning. PS 您应该将 function 声明为template<class T> int AdaBoost<T>::readFromFile(const char* fName)以摆脱deprecated conversion from string constant to 'char*'警告。 The function does not need to alter the filename. function 不需要更改文件名。

You cannot separate template class definition and implementation in different compilation units.您不能在不同的编译单元中分离模板 class 的定义和实现。 In other words, AdaBoost<T> complete implementation should be linked in the same compilation unit that main (where it is used) is.换句话说, AdaBoost<T>完整的实现应该链接在与main (使用它的地方)相同的编译单元中。

This is typically fixed by either #including the .cpp file at the end of your .hpp file (if you want to maintain them separate), or just using only the .hpp file implementing the whole class there.这通常通过.hpp #including文件末尾的.cpp文件(如果您想将它们分开维护)或仅使用实现整个 class 的.hpp文件来解决。

You have multiple problems.你有多个问题。

First, you use the unconventional technique of explicit instantiation in a CPP file.首先,您在 CPP 文件中使用显式实例化的非常规技术。 As others have pointed out, convention (but nothing more) requires that you put the implementation in the.H file to allow for generic instantiation.正如其他人指出的那样,约定(但仅此而已)要求您将实现放在 .H 文件中以允许通用实例化。 You don't have to do this, but if you did, the readfile() error would go away.你不必这样做,但如果你这样做了,readfile() 错误将 go 消失。 (As an alternative, put your AdaBoost<double> instantiation after the definition of AdaBoost::readfile .) (作为替代方案,将您的AdaBoost<double>实例化放在AdaBoost::readfile的定义之后。)

Next, you have declared, but not defined, your constructor and destructor.接下来,您已声明但未定义您的构造函数和析构函数。 If you wish to use the compiler-provided constructor and destructor you should delete the declarations.如果你想使用编译器提供的构造函数和析构函数,你应该删除声明。 If you wish to use your own constructor and dstructor, you should define them.如果您希望使用自己的构造函数和 dstructor,则应定义它们。

Best practice is to get rid of AdaBoost.cpp, and modify AdaBoost.h to include the implementation inline in the header.最佳实践是删除 AdaBoost.cpp,并修改 AdaBoost.h 以在 header 中包含内联实现。 (Note that this best practice is for templated classes; other advice may apply to non-templated classes.) (请注意,此最佳实践适用于模板类;其他建议可能适用于非模板类。)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM