尽管没有虚函数,但未定义对 Vtable 的引用
Despite no Virtual Functions, Undefined reference to Vtable
我有一个基础 class 和一个派生的 class、angelic_wing(派生的)和 angelic_event(基础的)。当我编译时,出现以下两个错误:
/tmp/ccG6KlZF.o: In function `angelic_wing::angelic_wing()':
angelicwing.cpp:(.text+0x20): undefined reference to `vtable for angelic_wing'
/tmp/ccG6KlZF.o: In function `angelic_wing::~angelic_wing()':
angelicwing.cpp:(.text+0x90): undefined reference to `vtable for angelic_wing'
collect2: error: ld returned 1 exit status
经过一些研究,问题似乎与未在基 class 中为虚函数定义主体有关。但是,由于以下原因,此问题似乎并非如此:
- 这些是派生的构造函数和析构函数 class,
因此不会在基础中声明或定义
class.
- None 中的构造函数和析构函数
派生 class 或基础 class 是 declared/defined 作为虚拟。
我当然在基础中使用虚函数 class。这是代码:
class angelic_event{
public:
angelic_event();
~angelic_event();
virtual void events(SDL_Event *event);
virtual void input_focus();
virtual void input_blur();
virtual void key_down(SDLKey sym, SDLMod mod, Uint16 unicode);
virtual void key_up(SDLKey sym, SDLMod mod, Uint16 unicode);
virtual void mouse_focus();
virtual void mouse_blur();
virtual void mouse_move(int x, int y, int rx, int ry, int left, int right, int middle);
virtual void mouse_wheel(int up, int down);
virtual void ml_button_down(int x, int y);
virtual void ml_button_up(int x, int y);
virtual void mr_button_down(int x, int y);
virtual void mr_button_up(int x, int y);
virtual void mm_button_down(int x, int y);
virtual void mm_button_up(int x, int y);
virtual void joy_axis(Uint8 which, Uint8 axis, Sint16 value);
virtual void joy_button_down(Uint8 which, Uint8 button);
virtual void joy_button_up(Uint8 which, Uint8 button);
virtual void joy_hat(Uint8 which, Uint8 hat, Uint8 value);
virtual void joy_ball(Uint8 which, Uint8 ball, Sint16 rx, Sint16 ry);
virtual void minimize();
virtual void restore();
virtual void resize(int w, int h);
virtual void expose();
virtual void flag_exit();
virtual void user_event(Uint8 type, int code, void *data1, void *data2);
};
不过,据我所知,我已经在 events.cpp 文件中定义了所有这些函数。另请注意,class 的构造函数和析构函数都不是虚函数。
另一方面,我的派生 class 根本没有声明任何虚函数。这是相关代码:
class angelic_wing : angelic_event{
int game_state;
int current_state;
angelic_clock game_clock;
int newtime;
int oldtime;
SDL_Event event;
SDL_Surface *screen;
private:
void init_bootstrap();
void init_mainmenu();
void init_pausemenu();
void init_gameover();
void init_gamewin();
void init_gamecredits();
void init_gameproper();
private:
void flag_exit();
void user_event(Uint8 type, int code, void *data1, void *data2);
public:
angelic_wing();
~angelic_wing();
int execute();
int initiate();
int destruct();
int process_event(SDL_Event *event);
int update();
int render();
int game_state_init(int current_state);
int check_time(float elapsed);
};
如您所见,没有一个虚函数。我不确定发生了什么,但我遇到的大多数信息都说要确保我已经定义了所有功能。然而,我无法反复检查,而且看起来我确实已经定义了所有这些。所以我 运行 别无选择。
但是,我认为有一件事可能有一定的相关性。我认为将 angelic_event class 的虚函数和 angelic_wing class 的重写函数保留在同一个 events.cpp 中是个好主意文件。然而,在这样做之后,我怀疑这可能是由于某种奇怪的巧合导致了 'undefined reference to `vtable for angelic_wing' 错误。
因此,我将覆盖的函数移动到 angelicwing.cpp 文件中,但无济于事。无论如何,问题仍然存在。
这里是 events.cpp 文件的完整代码,以防你们发现我遗漏的内容:
#include "events.hpp"
#include "angelicwing.hpp"
angelic_event :: angelic_event(){}
angelic_event :: ~angelic_event(){}
void angelic_event :: events(SDL_Event *event)
{
switch(event->type){
case SDL_ACTIVEEVENT:
switch(event->active.state){
case SDL_APPMOUSEFOCUS:
if(event->active.gain){
mouse_focus();
} else {
mouse_blur();
} break;
case SDL_APPINPUTFOCUS:
if(event->active.gain){
input_focus();
} else {
input_blur();
} break;
case SDL_APPACTIVE:
if(event->active.gain){
restore();
} else {
minimize();
} break;
} break;
case SDL_KEYDOWN:
key_down(event->key.keysym.sym, event->key.keysym.mod, event->key.keysym.unicode);
break;
case SDL_KEYUP:
key_up(event->key.keysym.sym, event->key.keysym.mod, event->key.keysym.unicode);
case SDL_MOUSEMOTION:
mouse_move(event->motion.x, event->motion.y, event->motion.xrel, event->motion.yrel,
(event->motion.state&SDL_BUTTON(SDL_BUTTON_LEFT))!=0,
(event->motion.state&SDL_BUTTON(SDL_BUTTON_RIGHT))!=0,
(event->motion.state&SDL_BUTTON(SDL_BUTTON_MIDDLE))!=0);
break;
case SDL_MOUSEBUTTONDOWN:
switch(event->button.button){
case SDL_BUTTON_LEFT:
ml_button_down(event->button.x, event->button.y);
break;
case SDL_BUTTON_RIGHT:
mr_button_down(event->button.x, event->button.y);
break;
case SDL_BUTTON_MIDDLE:
mm_button_down(event->button.x, event->button.y);
break;
} break;
case SDL_MOUSEBUTTONUP:
switch(event->button.button){
case SDL_BUTTON_LEFT:
ml_button_up(event->button.x, event->button.y);
break;
case SDL_BUTTON_RIGHT:
mr_button_up(event->button.x, event->button.y);
break;
case SDL_BUTTON_MIDDLE:
mm_button_up(event->button.x, event->button.y);
break;
} break;
case SDL_JOYAXISMOTION:
joy_axis(event->jaxis.which, event->jaxis.axis, event->jaxis.value);
break;
case SDL_JOYBALLMOTION:
joy_ball(event->jball.which, event->jball.ball, event->jball.xrel, event->jball.yrel);
break;
case SDL_JOYHATMOTION:
joy_hat(event->jhat.which, event->jhat.hat, event->jhat.value);
break;
case SDL_JOYBUTTONDOWN:
joy_button_down(event->jbutton.which, event->jbutton.button);
break;
case SDL_JOYBUTTONUP:
joy_button_up(event->jbutton.which, event->jbutton.button);
break;
case SDL_QUIT:
flag_exit();
break;
case SDL_SYSWMEVENT:
// ignore?
break;
case SDL_VIDEORESIZE:
resize(event->resize.w, event->resize.h);
break;
case SDL_VIDEOEXPOSE:
expose();
break;
default:
user_event(event->user.type, event->user.code, event->user.data1, event->user.data2);
break;
};
}
void angelic_event :: input_focus(){}
void angelic_event :: input_blur(){}
void angelic_event :: key_down(SDLKey sym, SDLMod mod, Uint16 unicode){}
void angelic_event :: key_up(SDLKey sym, SDLMod mod, Uint16 unicode){}
void angelic_event :: mouse_focus(){}
void angelic_event :: mouse_blur(){}
void angelic_event :: mouse_move(int x, int y, int rx, int ry, int left, int right, int middle){}
void angelic_event :: mouse_wheel(int up, int down){}
void angelic_event :: ml_button_down(int x, int y){}
void angelic_event :: ml_button_up(int x, int y){}
void angelic_event :: mr_button_down(int x, int y){}
void angelic_event :: mr_button_up(int x, int y){}
void angelic_event :: mm_button_down(int x, int y){}
void angelic_event :: mm_button_up(int x, int y){}
void angelic_event :: joy_axis(Uint8 which, Uint8 axis, Sint16 value){}
void angelic_event :: joy_button_down(Uint8 which, Uint8 button){}
void angelic_event :: joy_button_up(Uint8 which, Uint8 button){}
void angelic_event :: joy_hat(Uint8 which, Uint8 hat, Uint8 value){}
void angelic_event :: joy_ball(Uint8 which, Uint8 ball, Sint16 rx, Sint16 ry){}
void angelic_event :: minimize(){}
void angelic_event :: restore(){}
void angelic_event :: resize(int w, int h){}
void angelic_event :: expose(){}
void angelic_event :: flag_exit(){}
void angelic_event :: user_event(Uint8 type, int code, void *data1, void *data2){}
void angelic_wing :: user_event(Uint8 type, int code, void *data1, void *data2)
{
switch(code){
case CHANGE_GAME_MODE:
game_state = *((int *)data1);
break;
default:
break;
}
}
此外,如果可能有帮助,我应该告诉您一些关于我的系统的信息。我正在使用 GCC 版本 4.8.2(尽管我正在使用 g++ 命令进行编译)。我是 运行 64 位系统上的 Slackware 版本 14.1,没有 32 位兼容性文件等
我必须说,这对我来说真的很头疼。希望更有经验的伙伴们可以告诉我我做错了什么,或者可能是一种前进的方式。
非常感谢您的宝贵时间,
何塞·路易斯·A·努涅斯
您的派生 class 覆盖了基 class 中的至少两个虚函数:user_event
和 flag_exit
。缺少 virtual
说明符并不重要,这些是虚函数。 flag_exit
从未定义。
如果第一个虚函数未定义,您通常会遇到 "undefined reference to vtable" 错误。
我有一个基础 class 和一个派生的 class、angelic_wing(派生的)和 angelic_event(基础的)。当我编译时,出现以下两个错误:
/tmp/ccG6KlZF.o: In function `angelic_wing::angelic_wing()':
angelicwing.cpp:(.text+0x20): undefined reference to `vtable for angelic_wing'
/tmp/ccG6KlZF.o: In function `angelic_wing::~angelic_wing()':
angelicwing.cpp:(.text+0x90): undefined reference to `vtable for angelic_wing'
collect2: error: ld returned 1 exit status
经过一些研究,问题似乎与未在基 class 中为虚函数定义主体有关。但是,由于以下原因,此问题似乎并非如此:
- 这些是派生的构造函数和析构函数 class, 因此不会在基础中声明或定义 class.
- None 中的构造函数和析构函数 派生 class 或基础 class 是 declared/defined 作为虚拟。
我当然在基础中使用虚函数 class。这是代码:
class angelic_event{
public:
angelic_event();
~angelic_event();
virtual void events(SDL_Event *event);
virtual void input_focus();
virtual void input_blur();
virtual void key_down(SDLKey sym, SDLMod mod, Uint16 unicode);
virtual void key_up(SDLKey sym, SDLMod mod, Uint16 unicode);
virtual void mouse_focus();
virtual void mouse_blur();
virtual void mouse_move(int x, int y, int rx, int ry, int left, int right, int middle);
virtual void mouse_wheel(int up, int down);
virtual void ml_button_down(int x, int y);
virtual void ml_button_up(int x, int y);
virtual void mr_button_down(int x, int y);
virtual void mr_button_up(int x, int y);
virtual void mm_button_down(int x, int y);
virtual void mm_button_up(int x, int y);
virtual void joy_axis(Uint8 which, Uint8 axis, Sint16 value);
virtual void joy_button_down(Uint8 which, Uint8 button);
virtual void joy_button_up(Uint8 which, Uint8 button);
virtual void joy_hat(Uint8 which, Uint8 hat, Uint8 value);
virtual void joy_ball(Uint8 which, Uint8 ball, Sint16 rx, Sint16 ry);
virtual void minimize();
virtual void restore();
virtual void resize(int w, int h);
virtual void expose();
virtual void flag_exit();
virtual void user_event(Uint8 type, int code, void *data1, void *data2);
};
不过,据我所知,我已经在 events.cpp 文件中定义了所有这些函数。另请注意,class 的构造函数和析构函数都不是虚函数。
另一方面,我的派生 class 根本没有声明任何虚函数。这是相关代码:
class angelic_wing : angelic_event{
int game_state;
int current_state;
angelic_clock game_clock;
int newtime;
int oldtime;
SDL_Event event;
SDL_Surface *screen;
private:
void init_bootstrap();
void init_mainmenu();
void init_pausemenu();
void init_gameover();
void init_gamewin();
void init_gamecredits();
void init_gameproper();
private:
void flag_exit();
void user_event(Uint8 type, int code, void *data1, void *data2);
public:
angelic_wing();
~angelic_wing();
int execute();
int initiate();
int destruct();
int process_event(SDL_Event *event);
int update();
int render();
int game_state_init(int current_state);
int check_time(float elapsed);
};
如您所见,没有一个虚函数。我不确定发生了什么,但我遇到的大多数信息都说要确保我已经定义了所有功能。然而,我无法反复检查,而且看起来我确实已经定义了所有这些。所以我 运行 别无选择。
但是,我认为有一件事可能有一定的相关性。我认为将 angelic_event class 的虚函数和 angelic_wing class 的重写函数保留在同一个 events.cpp 中是个好主意文件。然而,在这样做之后,我怀疑这可能是由于某种奇怪的巧合导致了 'undefined reference to `vtable for angelic_wing' 错误。
因此,我将覆盖的函数移动到 angelicwing.cpp 文件中,但无济于事。无论如何,问题仍然存在。
这里是 events.cpp 文件的完整代码,以防你们发现我遗漏的内容:
#include "events.hpp"
#include "angelicwing.hpp"
angelic_event :: angelic_event(){}
angelic_event :: ~angelic_event(){}
void angelic_event :: events(SDL_Event *event)
{
switch(event->type){
case SDL_ACTIVEEVENT:
switch(event->active.state){
case SDL_APPMOUSEFOCUS:
if(event->active.gain){
mouse_focus();
} else {
mouse_blur();
} break;
case SDL_APPINPUTFOCUS:
if(event->active.gain){
input_focus();
} else {
input_blur();
} break;
case SDL_APPACTIVE:
if(event->active.gain){
restore();
} else {
minimize();
} break;
} break;
case SDL_KEYDOWN:
key_down(event->key.keysym.sym, event->key.keysym.mod, event->key.keysym.unicode);
break;
case SDL_KEYUP:
key_up(event->key.keysym.sym, event->key.keysym.mod, event->key.keysym.unicode);
case SDL_MOUSEMOTION:
mouse_move(event->motion.x, event->motion.y, event->motion.xrel, event->motion.yrel,
(event->motion.state&SDL_BUTTON(SDL_BUTTON_LEFT))!=0,
(event->motion.state&SDL_BUTTON(SDL_BUTTON_RIGHT))!=0,
(event->motion.state&SDL_BUTTON(SDL_BUTTON_MIDDLE))!=0);
break;
case SDL_MOUSEBUTTONDOWN:
switch(event->button.button){
case SDL_BUTTON_LEFT:
ml_button_down(event->button.x, event->button.y);
break;
case SDL_BUTTON_RIGHT:
mr_button_down(event->button.x, event->button.y);
break;
case SDL_BUTTON_MIDDLE:
mm_button_down(event->button.x, event->button.y);
break;
} break;
case SDL_MOUSEBUTTONUP:
switch(event->button.button){
case SDL_BUTTON_LEFT:
ml_button_up(event->button.x, event->button.y);
break;
case SDL_BUTTON_RIGHT:
mr_button_up(event->button.x, event->button.y);
break;
case SDL_BUTTON_MIDDLE:
mm_button_up(event->button.x, event->button.y);
break;
} break;
case SDL_JOYAXISMOTION:
joy_axis(event->jaxis.which, event->jaxis.axis, event->jaxis.value);
break;
case SDL_JOYBALLMOTION:
joy_ball(event->jball.which, event->jball.ball, event->jball.xrel, event->jball.yrel);
break;
case SDL_JOYHATMOTION:
joy_hat(event->jhat.which, event->jhat.hat, event->jhat.value);
break;
case SDL_JOYBUTTONDOWN:
joy_button_down(event->jbutton.which, event->jbutton.button);
break;
case SDL_JOYBUTTONUP:
joy_button_up(event->jbutton.which, event->jbutton.button);
break;
case SDL_QUIT:
flag_exit();
break;
case SDL_SYSWMEVENT:
// ignore?
break;
case SDL_VIDEORESIZE:
resize(event->resize.w, event->resize.h);
break;
case SDL_VIDEOEXPOSE:
expose();
break;
default:
user_event(event->user.type, event->user.code, event->user.data1, event->user.data2);
break;
};
}
void angelic_event :: input_focus(){}
void angelic_event :: input_blur(){}
void angelic_event :: key_down(SDLKey sym, SDLMod mod, Uint16 unicode){}
void angelic_event :: key_up(SDLKey sym, SDLMod mod, Uint16 unicode){}
void angelic_event :: mouse_focus(){}
void angelic_event :: mouse_blur(){}
void angelic_event :: mouse_move(int x, int y, int rx, int ry, int left, int right, int middle){}
void angelic_event :: mouse_wheel(int up, int down){}
void angelic_event :: ml_button_down(int x, int y){}
void angelic_event :: ml_button_up(int x, int y){}
void angelic_event :: mr_button_down(int x, int y){}
void angelic_event :: mr_button_up(int x, int y){}
void angelic_event :: mm_button_down(int x, int y){}
void angelic_event :: mm_button_up(int x, int y){}
void angelic_event :: joy_axis(Uint8 which, Uint8 axis, Sint16 value){}
void angelic_event :: joy_button_down(Uint8 which, Uint8 button){}
void angelic_event :: joy_button_up(Uint8 which, Uint8 button){}
void angelic_event :: joy_hat(Uint8 which, Uint8 hat, Uint8 value){}
void angelic_event :: joy_ball(Uint8 which, Uint8 ball, Sint16 rx, Sint16 ry){}
void angelic_event :: minimize(){}
void angelic_event :: restore(){}
void angelic_event :: resize(int w, int h){}
void angelic_event :: expose(){}
void angelic_event :: flag_exit(){}
void angelic_event :: user_event(Uint8 type, int code, void *data1, void *data2){}
void angelic_wing :: user_event(Uint8 type, int code, void *data1, void *data2)
{
switch(code){
case CHANGE_GAME_MODE:
game_state = *((int *)data1);
break;
default:
break;
}
}
此外,如果可能有帮助,我应该告诉您一些关于我的系统的信息。我正在使用 GCC 版本 4.8.2(尽管我正在使用 g++ 命令进行编译)。我是 运行 64 位系统上的 Slackware 版本 14.1,没有 32 位兼容性文件等
我必须说,这对我来说真的很头疼。希望更有经验的伙伴们可以告诉我我做错了什么,或者可能是一种前进的方式。
非常感谢您的宝贵时间, 何塞·路易斯·A·努涅斯
您的派生 class 覆盖了基 class 中的至少两个虚函数:user_event
和 flag_exit
。缺少 virtual
说明符并不重要,这些是虚函数。 flag_exit
从未定义。
如果第一个虚函数未定义,您通常会遇到 "undefined reference to vtable" 错误。