构造函数中的未定义引用
Undefined Reference in constructors
过去 2 天我一直在研究这个问题,我已经尝试了互联网上的每一个解决方案,所以就这样吧。
我对未定义的引用有疑问。我正在做一个比较 3 种算法的项目,我将它们划分为 3 组不同的 cpp 文件。我使用带有 gcc 4.9.2.6 的 Dev C++ 作为我的编译器。我知道这是一个 linker 错误,但我所有的解决方案都不起作用,我似乎无法识别它。
我的主文件是
#include <iostream>
#include <stdio.h>
#include <string>
#include <fstream>
#include <time.h>
#include "SDL.h"
#include "bitmap_image.hpp" //ext
#include "Bresenham.hpp"
#include "XiaolinWu.hpp"
#include "GuptaSproull.hpp"
void GenerateBMPBlank(int xsize,int ysize,std::string fileid);
void BresenhamTest(int xsize,int ysize, std::string TestDataFile);
void XiaolinWuTest(int xsize,int ysize, std::string TestDataFile);
void GuptaSproullTest(int xsize, int ysize, std::string TestDataFile);
void executeTest(int xsize,int ysize, std::string TestDataFile); //resulting BMP file generated will have the format "x_y_algorithmName.bmp"
int main()
{
short x,y;
std::string TestFileLocation;
std::cout << "Please indicate file path of Test Data textfile"<< std::endl;
std::cin>>TestFileLocation;
std::cout << "Please indicate file dimensions" << std::endl;
std::cin>> x >> y;
executeTest(x,y, TestFileLocation);
std::cout<< "Procedure executed"<< std::endl;
std::cin.get();
return 0;
}
void GenerateBMPBlank(int xsize,int ysize,std::string fileid) //uses external library http://partow.net/programming/bitmap/ to generate a blank white bmp file
{
bitmap_image blankBMP(xsize,ysize); //creates bitmap image
blankBMP.set_all_channels(255,255,255); //sets entire image to be completely white
blankBMP.save_image(fileid);
} //tested
void executeTest(int xsize,int ysize, std::string TestDataFile)
{
SDL_Init( SDL_INIT_EVERYTHING );
std::cout<<"Beginning test of data set from "+TestDataFile<<std::endl;
std::cout<<"Now executing Bresenham's algorithm"<<std::endl;
BresenhamTest(xsize,ysize, TestDataFile);
std::cout<<"Now executing Xiaolin Wu's algorithm"<<std::endl;
XiaolinWuTest(xsize,ysize,TestDataFile);
std::cout<<"Now executing Gupta Sproull 's algorithm"<<std::endl;
GuptaSproullTest(xsize,ysize,TestDataFile);
SDL_Quit();
}
void BresenhamTest(int xsize,int ysize, std::string TestDataFile)
{
std::string ResultName= std::to_string(xsize) + "_" + std::to_string(ysize) + "_Bresenham.bmp";
GenerateBMPBlank(xsize,ysize,ResultName);
clock_t tStart = clock();
Bresenham b(ResultName,TestDataFile);
printf("Time taken for Bresenham: %.4fs\n", (double)(clock() - tStart)/CLOCKS_PER_SEC);
}
void XiaolinWuTest(int xsize,int ysize, std::string TestDataFile)
{
std::string ResultName= std::to_string(xsize) + "_" + std::to_string(ysize) + "_XiaolinWu.bmp";
GenerateBMPBlank(xsize,ysize,ResultName);
clock_t tStart = clock();
XiaolinWu w(ResultName,TestDataFile);
printf("Time taken for XiaolinWu: %.4fs\n", (double)(clock() - tStart)/CLOCKS_PER_SEC);
}
void GuptaSproullTest(int xsize,int ysize, std::string TestDataFile)
{
std::string ResultName= std::to_string(xsize) + "_" + std::to_string(ysize) + "_GuptaSproull.bmp";
GenerateBMPBlank(xsize,ysize,ResultName);
clock_t tStart = clock();
GuptaSproull g(ResultName,TestDataFile);
printf("Time taken for GuptaSproull: %.4fs\n", (double)(clock() - tStart)/CLOCKS_PER_SEC);
}
但是报错如下
C++ files/ComparatorMain.o:ComparatorMain.cpp:(.text+0x544): undefined reference to `Bresenham::Bresenham(std::string, std::string)'
C++ files/ComparatorMain.o:ComparatorMain.cpp:(.text+0x76b): undefined reference to `XiaolinWu::XiaolinWu(std::string, std::string)'
C++ files/ComparatorMain.o:ComparatorMain.cpp:(.text+0x992): undefined reference to `GuptaSproull::GuptaSproull(std::string, std::string)'collect2.exe: error: ld returned 1 exit status
由于 3 个不同的 cpp 文件的实现几乎完全相同(主要区别仅在于实现的算法以及一些杂项。函数已经符合但到目前为止没有显示错误),我只会显示 Bresenham.cpp 和 hpp 的主要部分,其中出现 linker 错误(如果需要其他信息,请告诉我)。 GuptaSproull.cpp 和 XiaolinWu.cpp 的定义与下面显示的代码几乎相同。为了便于阅读,我删除了大部分函数实现,我认为它不相关(除非我弄错了那部分)。
Bresenham.hpp
#ifndef BRESENHAM_H
#define BRESENHAM_H
#include <iostream>
#include "SDL.h"
#undef main
class Bresenham{
public:
Bresenham(std::string BMPName,std::string TestDataFile);
SDL_Surface* OpenBMP(std::string BMPName);
void CloseBMP(SDL_Surface* surface,std::string Filename);
void putpixel(SDL_Surface *surface, int x, int y, Uint32 pixel);
void bresenhamDrawLine(int x1,int y1,int x2, int y2, SDL_Surface *surface);
};
#endif
Bresenham.cpp
#ifndef BRESENHAM_H
#define BRESENHAM_H
#include <iostream>
#include <cstdio>
#include <cmath>
#include <fstream>
#include "SDL.h"
#include "Bresenham.hpp"
#undef main
#endif
class Bresenham
{
Bresenham(std::string BMPName,std::string TestDataFile)
{
std::ifstream testFile(TestDataFile);
SDL_Surface *image;
image=OpenBMP(BMPName);
if ( SDL_MUSTLOCK(image) ) //surface must be locked before pixels can be drawn
{
if ( SDL_LockSurface(image) < 0 ) {
fprintf(stderr, "Can't lock screen: %s\n", SDL_GetError());
return;
}
}
int x1,y1,x2,y2;
while(testFile>>x1>>y1>>x2>>y2)
{
bresenhamDrawLine(x1,y1,x2,y2,image); //loops through the dataset and calls the bresenham draw line function
}
if ( SDL_MUSTLOCK(image) )
{
SDL_UnlockSurface(image);
}
CloseBMP(image,BMPName);
}
void bresenhamDrawLine(int x1,int y1,int x2, int y2, SDL_Surface *surface)
{
/* implemented */
}
SDL_Surface* OpenBMP(std::string BMPName)
{
/* implemented */
}
void CloseBMP(SDL_Surface *surface,std::string FileName)
{
/* implemented */
}
void putpixel(SDL_Surface *surface, int x, int y, double brightness) //this function allows us to place a pixel at coordinates (x,y) in SDL.
{
/*implemented*/
}
};
现在我做了一些乱七八糟的尝试来尝试解决这个问题(比如在.cpp文件中添加#ifndef BRESENHAM_H #define BRESENHAM_H #include "Bresenham.hpp"
。但是,上面的错误仍然出现。
这 link 是否符合我执行代码以进行测试的方式?我使用一个构造函数来基本上 运行 我对算法的测试(我怀疑你可能会找到实现这种测试的劣质方法)。我已经完成了以下操作(是的,那些没有用):
- 已验证所有文件都在构建路径中(在同一项目下)
- 尝试添加命名空间以查看是否解决了问题(没有解决)
- 我几乎在 google 中的每个 link 下进行了搜索,以找到可能的修复方法(其中 none 似乎有效)。
- 到目前为止(在所有文件中)没有编译器错误。
我怀疑我可能需要放弃这种实现测试的方式,转而使用静态函数(如果这可行,有人可以发表评论吗?)。我不太习惯 C++(这是我迄今为止用这种语言编写的第一个 "big" 程序),如果我遗漏了一些非常明显的东西(我希望我没有遗漏),请原谅我。
我该怎么办?
What should I do?
首先,您需要设置正确的编码单位:
- 删除
#undef main
(没有意义)
- 从您的 cpp 文件中删除 include guards,它们只属于头文件。有了这些,代码就不会被编译,因此会出现链接问题!
- 正如 CodeFuller 在他的回答中明确指出的那样,您必须将 class 声明(在 .hpp 文件中)和方法的实现(在 .cpp 文件中)分开
要了解更多信息,您需要给我们一个 MVCE 来证明您的问题(我同意,这是一些工作)。
您实际上有两个 Bresenham class 声明,一个在 Bresenham.hpp 中,一个在 Bresenham.cpp 中。按照以下方式更改您的 cpp 文件:
Bresenham::Bresenham(std::string BMPName,std::string TestDataFile)
{
std::ifstream testFile(TestDataFile);
SDL_Surface *image;
image=OpenBMP(BMPName);
if ( SDL_MUSTLOCK(image) ) //surface must be locked before pixels can be drawn
{
if ( SDL_LockSurface(image) < 0 ) {
fprintf(stderr, "Can't lock screen: %s\n", SDL_GetError());
return;
}
}
int x1,y1,x2,y2;
while(testFile>>x1>>y1>>x2>>y2)
{
bresenhamDrawLine(x1,y1,x2,y2,image); //loops through the dataset and calls the bresenham draw line function
}
if ( SDL_MUSTLOCK(image) )
{
SDL_UnlockSurface(image);
}
CloseBMP(image,BMPName);
}
void Bresenham::bresenhamDrawLine(int x1,int y1,int x2, int y2, SDL_Surface *surface)
{
/* implemented */
}
SDL_Surface* Bresenham::OpenBMP(std::string BMPName)
{
/* implemented */
}
void Bresenham::CloseBMP(SDL_Surface *surface,std::string FileName)
{
/* implemented */
}
void Bresenham::putpixel(SDL_Surface *surface, int x, int y, double brightness) //this function allows us to place a pixel at coordinates (x,y) in SDL.
{
/*implemented*/
}
过去 2 天我一直在研究这个问题,我已经尝试了互联网上的每一个解决方案,所以就这样吧。
我对未定义的引用有疑问。我正在做一个比较 3 种算法的项目,我将它们划分为 3 组不同的 cpp 文件。我使用带有 gcc 4.9.2.6 的 Dev C++ 作为我的编译器。我知道这是一个 linker 错误,但我所有的解决方案都不起作用,我似乎无法识别它。
我的主文件是
#include <iostream>
#include <stdio.h>
#include <string>
#include <fstream>
#include <time.h>
#include "SDL.h"
#include "bitmap_image.hpp" //ext
#include "Bresenham.hpp"
#include "XiaolinWu.hpp"
#include "GuptaSproull.hpp"
void GenerateBMPBlank(int xsize,int ysize,std::string fileid);
void BresenhamTest(int xsize,int ysize, std::string TestDataFile);
void XiaolinWuTest(int xsize,int ysize, std::string TestDataFile);
void GuptaSproullTest(int xsize, int ysize, std::string TestDataFile);
void executeTest(int xsize,int ysize, std::string TestDataFile); //resulting BMP file generated will have the format "x_y_algorithmName.bmp"
int main()
{
short x,y;
std::string TestFileLocation;
std::cout << "Please indicate file path of Test Data textfile"<< std::endl;
std::cin>>TestFileLocation;
std::cout << "Please indicate file dimensions" << std::endl;
std::cin>> x >> y;
executeTest(x,y, TestFileLocation);
std::cout<< "Procedure executed"<< std::endl;
std::cin.get();
return 0;
}
void GenerateBMPBlank(int xsize,int ysize,std::string fileid) //uses external library http://partow.net/programming/bitmap/ to generate a blank white bmp file
{
bitmap_image blankBMP(xsize,ysize); //creates bitmap image
blankBMP.set_all_channels(255,255,255); //sets entire image to be completely white
blankBMP.save_image(fileid);
} //tested
void executeTest(int xsize,int ysize, std::string TestDataFile)
{
SDL_Init( SDL_INIT_EVERYTHING );
std::cout<<"Beginning test of data set from "+TestDataFile<<std::endl;
std::cout<<"Now executing Bresenham's algorithm"<<std::endl;
BresenhamTest(xsize,ysize, TestDataFile);
std::cout<<"Now executing Xiaolin Wu's algorithm"<<std::endl;
XiaolinWuTest(xsize,ysize,TestDataFile);
std::cout<<"Now executing Gupta Sproull 's algorithm"<<std::endl;
GuptaSproullTest(xsize,ysize,TestDataFile);
SDL_Quit();
}
void BresenhamTest(int xsize,int ysize, std::string TestDataFile)
{
std::string ResultName= std::to_string(xsize) + "_" + std::to_string(ysize) + "_Bresenham.bmp";
GenerateBMPBlank(xsize,ysize,ResultName);
clock_t tStart = clock();
Bresenham b(ResultName,TestDataFile);
printf("Time taken for Bresenham: %.4fs\n", (double)(clock() - tStart)/CLOCKS_PER_SEC);
}
void XiaolinWuTest(int xsize,int ysize, std::string TestDataFile)
{
std::string ResultName= std::to_string(xsize) + "_" + std::to_string(ysize) + "_XiaolinWu.bmp";
GenerateBMPBlank(xsize,ysize,ResultName);
clock_t tStart = clock();
XiaolinWu w(ResultName,TestDataFile);
printf("Time taken for XiaolinWu: %.4fs\n", (double)(clock() - tStart)/CLOCKS_PER_SEC);
}
void GuptaSproullTest(int xsize,int ysize, std::string TestDataFile)
{
std::string ResultName= std::to_string(xsize) + "_" + std::to_string(ysize) + "_GuptaSproull.bmp";
GenerateBMPBlank(xsize,ysize,ResultName);
clock_t tStart = clock();
GuptaSproull g(ResultName,TestDataFile);
printf("Time taken for GuptaSproull: %.4fs\n", (double)(clock() - tStart)/CLOCKS_PER_SEC);
}
但是报错如下
C++ files/ComparatorMain.o:ComparatorMain.cpp:(.text+0x544): undefined reference to `Bresenham::Bresenham(std::string, std::string)'
C++ files/ComparatorMain.o:ComparatorMain.cpp:(.text+0x76b): undefined reference to `XiaolinWu::XiaolinWu(std::string, std::string)'
C++ files/ComparatorMain.o:ComparatorMain.cpp:(.text+0x992): undefined reference to `GuptaSproull::GuptaSproull(std::string, std::string)'collect2.exe: error: ld returned 1 exit status
由于 3 个不同的 cpp 文件的实现几乎完全相同(主要区别仅在于实现的算法以及一些杂项。函数已经符合但到目前为止没有显示错误),我只会显示 Bresenham.cpp 和 hpp 的主要部分,其中出现 linker 错误(如果需要其他信息,请告诉我)。 GuptaSproull.cpp 和 XiaolinWu.cpp 的定义与下面显示的代码几乎相同。为了便于阅读,我删除了大部分函数实现,我认为它不相关(除非我弄错了那部分)。 Bresenham.hpp
#ifndef BRESENHAM_H
#define BRESENHAM_H
#include <iostream>
#include "SDL.h"
#undef main
class Bresenham{
public:
Bresenham(std::string BMPName,std::string TestDataFile);
SDL_Surface* OpenBMP(std::string BMPName);
void CloseBMP(SDL_Surface* surface,std::string Filename);
void putpixel(SDL_Surface *surface, int x, int y, Uint32 pixel);
void bresenhamDrawLine(int x1,int y1,int x2, int y2, SDL_Surface *surface);
};
#endif
Bresenham.cpp
#ifndef BRESENHAM_H
#define BRESENHAM_H
#include <iostream>
#include <cstdio>
#include <cmath>
#include <fstream>
#include "SDL.h"
#include "Bresenham.hpp"
#undef main
#endif
class Bresenham
{
Bresenham(std::string BMPName,std::string TestDataFile)
{
std::ifstream testFile(TestDataFile);
SDL_Surface *image;
image=OpenBMP(BMPName);
if ( SDL_MUSTLOCK(image) ) //surface must be locked before pixels can be drawn
{
if ( SDL_LockSurface(image) < 0 ) {
fprintf(stderr, "Can't lock screen: %s\n", SDL_GetError());
return;
}
}
int x1,y1,x2,y2;
while(testFile>>x1>>y1>>x2>>y2)
{
bresenhamDrawLine(x1,y1,x2,y2,image); //loops through the dataset and calls the bresenham draw line function
}
if ( SDL_MUSTLOCK(image) )
{
SDL_UnlockSurface(image);
}
CloseBMP(image,BMPName);
}
void bresenhamDrawLine(int x1,int y1,int x2, int y2, SDL_Surface *surface)
{
/* implemented */
}
SDL_Surface* OpenBMP(std::string BMPName)
{
/* implemented */
}
void CloseBMP(SDL_Surface *surface,std::string FileName)
{
/* implemented */
}
void putpixel(SDL_Surface *surface, int x, int y, double brightness) //this function allows us to place a pixel at coordinates (x,y) in SDL.
{
/*implemented*/
}
};
现在我做了一些乱七八糟的尝试来尝试解决这个问题(比如在.cpp文件中添加#ifndef BRESENHAM_H #define BRESENHAM_H #include "Bresenham.hpp"
。但是,上面的错误仍然出现。
这 link 是否符合我执行代码以进行测试的方式?我使用一个构造函数来基本上 运行 我对算法的测试(我怀疑你可能会找到实现这种测试的劣质方法)。我已经完成了以下操作(是的,那些没有用):
- 已验证所有文件都在构建路径中(在同一项目下)
- 尝试添加命名空间以查看是否解决了问题(没有解决)
- 我几乎在 google 中的每个 link 下进行了搜索,以找到可能的修复方法(其中 none 似乎有效)。
- 到目前为止(在所有文件中)没有编译器错误。
我怀疑我可能需要放弃这种实现测试的方式,转而使用静态函数(如果这可行,有人可以发表评论吗?)。我不太习惯 C++(这是我迄今为止用这种语言编写的第一个 "big" 程序),如果我遗漏了一些非常明显的东西(我希望我没有遗漏),请原谅我。
我该怎么办?
What should I do?
首先,您需要设置正确的编码单位:
- 删除
#undef main
(没有意义) - 从您的 cpp 文件中删除 include guards,它们只属于头文件。有了这些,代码就不会被编译,因此会出现链接问题!
- 正如 CodeFuller 在他的回答中明确指出的那样,您必须将 class 声明(在 .hpp 文件中)和方法的实现(在 .cpp 文件中)分开
要了解更多信息,您需要给我们一个 MVCE 来证明您的问题(我同意,这是一些工作)。
您实际上有两个 Bresenham class 声明,一个在 Bresenham.hpp 中,一个在 Bresenham.cpp 中。按照以下方式更改您的 cpp 文件:
Bresenham::Bresenham(std::string BMPName,std::string TestDataFile)
{
std::ifstream testFile(TestDataFile);
SDL_Surface *image;
image=OpenBMP(BMPName);
if ( SDL_MUSTLOCK(image) ) //surface must be locked before pixels can be drawn
{
if ( SDL_LockSurface(image) < 0 ) {
fprintf(stderr, "Can't lock screen: %s\n", SDL_GetError());
return;
}
}
int x1,y1,x2,y2;
while(testFile>>x1>>y1>>x2>>y2)
{
bresenhamDrawLine(x1,y1,x2,y2,image); //loops through the dataset and calls the bresenham draw line function
}
if ( SDL_MUSTLOCK(image) )
{
SDL_UnlockSurface(image);
}
CloseBMP(image,BMPName);
}
void Bresenham::bresenhamDrawLine(int x1,int y1,int x2, int y2, SDL_Surface *surface)
{
/* implemented */
}
SDL_Surface* Bresenham::OpenBMP(std::string BMPName)
{
/* implemented */
}
void Bresenham::CloseBMP(SDL_Surface *surface,std::string FileName)
{
/* implemented */
}
void Bresenham::putpixel(SDL_Surface *surface, int x, int y, double brightness) //this function allows us to place a pixel at coordinates (x,y) in SDL.
{
/*implemented*/
}