“未定义的引用”在 Ubuntu 上链接
我对 C & 比较陌生。 C++ 并坚持编译(或者我应该说链接)整整两天。任何人给我一个想法将不胜感激。 下面是错误消息和 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 ****
Note-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;
}
I'm relatively new to C & C++ and stuck at compiling (or should I say linking) for the whole 2 days. Anyone gives me an idea would be appreciated.
Error message and 3 code files are below. 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
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. I receive the same result when I execute g++ on terminal.
Note-2. The path of .o files in the argument for linker should be correct (./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;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
如果您使用显式实例化,则必须在实例化类之前定义成员函数的通用版本:
但是,如果您首先没有使用显式实例化的特定或紧迫原因,请采用其他建议并在标题中定义模板。
If you are using explicit instantiation, you have to define the generic version of the member function before instantiating the class:
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.
不能将模板类的定义和实现分离在不同的编译单元中。换句话说,
AdaBoost
完整实现应该链接到main
(使用它的地方)所在的同一编译单元中。这通常可以通过
.hpp
文件末尾的#include
和.cpp
文件来修复(如果您想将它们分开) ,或者仅使用.hpp
文件实现整个类。You cannot separate template class definition and implementation in different compilation units. In other words,
AdaBoost<T>
complete implementation should be linked in the same compilation unit thatmain
(where it is used) is.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.你有很多问题。
首先,您在 CPP 文件中使用显式实例化的非常规技术。正如其他人指出的那样,约定(但仅此而已)要求您将实现放在 .H 文件中以允许通用实例化。您不必这样做,但如果您这样做,readfile() 错误就会消失。 (作为替代方案,将您的
AdaBoost
实例化放在AdaBoost::readfile
的定义之后。)接下来,您已经声明了,但是未定义,您的构造函数和析构函数。如果您希望使用编译器提供的构造函数和析构函数,您应该删除这些声明。如果您希望使用自己的构造函数和dstructor,则应该定义它们。
最佳实践是删除 AdaBoost.cpp,并修改 AdaBoost.h 以在标头中包含内联实现。 (请注意,此最佳实践适用于模板类;其他建议可能适用于非模板类。)
You have multiple problems.
First, you use the unconventional technique of explicit instantiation in a CPP file. As others have pointed out, convention (but nothing more) requires that you put the implementation in the .H file to allow for generic instantiation. You don't have to do this, but if you did, the readfile() error would go away. (As an alternative, put your
AdaBoost<double>
instantiation after the definition ofAdaBoost::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.
Best practice is to get rid of AdaBoost.cpp, and modify AdaBoost.h to include the implementation inline in the header. (Note that this best practice is for templated classes; other advice may apply to non-templated classes.)
您需要将
template的定义放在::readFromFile(char* fName)
到int AdaBoost
AdaBoost.h
中,并从构建中删除AdaBoost.cpp
。最好将所有模板代码放入标头中。 C++ 链接器需要消除模板代码的重复实例化,这样您就不会出现“多重定义的符号”错误。
PS 您应该将函数声明为
template;::readFromFile(const char* fName)
来消除int AdaBoost
已弃用的从字符串常量到“char*”的转换
警告。该函数不需要更改文件名。You need to put the definition of
template<class T>
intoint AdaBoost<T>::readFromFile(char* fName)
AdaBoost.h
, and removeAdaBoost.cpp
from your build.It's best to put all template code into the header. C++ linkers are required to eliminate duplicate instantiations of template code so you won't get "multiply defined symbol" errors.
P.S. You should declare the function as
template<class T>
to get rid of theint AdaBoost<T>::readFromFile(const char* fName)
deprecated conversion from string constant to ‘char*’
warning. The function does not need to alter the filename.