When I declare an event table in a class a.k.a DECLARE_EVENT_TABLE(); then try to compile, i always get this error:
[Linker Error] undefined reference to `vtable for Utility' (utility being my class) What does this mean and how do I fix it? All research on this has turned up dead ends =(. Thanks

Dani AI

Generated

Short answer and context

The linker error "undefined reference to vtable for Utility" happens because the DECLARE_EVENT_TABLE() macro adds event-table-related symbols (effectively the class has extra non-inline virtual machinery) that must be defined in one translation unit. If the corresponding event-table definition or the object file that contains it is missing, the linker complains. and pointed you to the right place: you need the event-table implementation (or to remove the macro if you don't use it). (tool.oschina.net)

Why this error appears (brief)

Compilers normally emit a class's vtable in the translation unit that defines the class's first non-inline "key" virtual function. If that definition is missing (or the .o is not linked) the vtable is unresolved and you get the message you saw. A common practical cause in wxWidgets is using DECLARE_EVENT_TABLE in the header without providing the matching implementation in a compiled .cpp. Another common cause is a missing out‑of‑line definition for a virtual destructor — adding a trivial destructor implementation often exposes the real missing symbol. (stackoverflow.com)

Practical fixes and modern alternative

  • If you want static event tables: make sure the event table implementation is present in exactly one .cpp (use the matching macros and the correct class name) and that .cpp is compiled and linked.

  • If you prefer a cleaner, modern approach, replace the static macros with Bind (or Connect) calls in the constructor; Bind avoids the need for the DECLARE/BEGIN/END macros. Example pattern:

    // in Utility constructor (after creating the button)
    Bind(wxEVT_BUTTON, &Utility::OnSend, this, btn_send);
    
    void Utility::OnSend(wxCommandEvent& evt)
    {
        // handle send
    }

    The wxWidgets project itself recommends using Bind/Connect in new code. (wxwidgets.org)

Quick troubleshooting checklist

  • Confirm the .cpp that contains the event-table implementation is part of the build.
  • Ensure the class name in the implementation matches the header exactly.
  • If the error persists, add an empty out‑of‑line destructor implementation (e.g. Utility::~Utility() {}) to force emission of the vtable and reveal any other missing definitions.
  • Do a full clean rebuild after changes.

Relevant posts: was right to look at the event-table macro, and correctly noted the implementation must exist — that change is exactly what resolves the vtable link error in this scenario. (tool.oschina.net)

Recommended Answers

All 5 Replies

Presumably something needs to be declared as virtual in Utility. Without code, it's hard to say exactly what.

Here is my Header file:

#ifndef UTILITY_H
#define UTILITY_H

#include <wx/wx.h>

enum
{
    btn_send = 100,
    btn_main,
    im_box_rec,
    im_box_ent,
    im_box_con,
    im_box_addip,
    im_combo
};

class Utility : public wxFrame
{
    public:
        Utility(const wxString &title, const wxPoint &pos, const wxSize &size);

    private:
       DECLARE_EVENT_TABLE();

};

#endif

And here is my .cpp:

#include "Utility.h"
#include <wx/wx.h>

Utility::Utility(const wxString &title, const wxPoint &pos, const wxSize &size) : wxFrame(NULL, -1, title, pos, size)
{
    /////////////////////////MENU////////////////////////////////


    wxMenu *util_list = new wxMenu;

    util_list -> Append(-1, _T("&"));
    util_list -> Append(-1, _T("&"));
    util_list -> Append(-1, _T("&"));
    util_list -> AppendSeparator();
    util_list -> Append(-1, _T("&About"));
    util_list -> AppendSeparator();
    util_list -> Append(-1, _T("E&xit"));

    wxMenuBar *MENU = new wxMenuBar;

    MENU -> Append(util_list, _T("&Utilities"));

    SetMenuBar(MENU);

    ///////////////////////PANELS/////////////////////////////

    wxPanel *mainPanel = new wxPanel(this, -1, wxPoint(0,0), wxSize(1000,600), wxBORDER_STATIC);
    wxPanel *sideWin = new wxPanel(mainPanel, -1, wxPoint(800,0), wxSize(200,500), wxBORDER_STATIC);

    wxTextCtrl *imBox_rec = new wxTextCtrl(mainPanel, im_box_rec, _T("Recieve text..."), wxPoint(0, 50), wxSize(400,200));
    wxTextCtrl *imBox_ent = new wxTextCtrl(mainPanel, im_box_ent, _T("Enter text..."), wxPoint(0,300), wxSize(400,100));

    wxComboBox *imCombo = new wxComboBox(mainPanel, im_combo, _T("IP List"), wxPoint(100, 25), wxSize(152, 100));

    wxButton *saveTran = new wxButton(mainPanel, -1, _T("Save Transcript"), wxPoint(0, 252), wxSize(400, 20));
    wxButton *addipButton = new wxButton(mainPanel, im_box_addip, _T("Add IP"), wxPoint(100,0), wxSize(150,25));
    wxButton *conButton = new wxButton(mainPanel, im_box_con, _T("Connect to IP"), wxPoint(0,0), wxSize(100,50));
    wxButton *mainButton = new wxButton(mainPanel, btn_main, _T("entr"), wxPoint(300,60), wxSize(100,100));
    wxButton *sendButton = new wxButton(mainPanel, btn_send, _T("Send"), wxPoint(0,400), wxSize(400,50));

    wxBoxSizer *mainSizer = new wxBoxSizer(wxVERTICAL);

    mainSizer -> Add(imBox_rec, 0, wxCENTER, 0);
    mainSizer -> Add(imBox_ent, 0, wxCENTER, 0);
    mainSizer -> Add(mainButton, 0, wxCENTER, 0);
    mainSizer -> Add(sendButton, 0, wxCENTER, 0);

    //mainPanel -> SetAutoLayout(true);
    //mainPanel -> SetSizer(mainSizer);

}

I don't know wxWidgets, so I'm just guessing here. Try making DECLARE_EVENT_TABLE(); public instead of private.

If that doesn't work, try putting this in your code:

BEGIN_EVENT_TABLE(MyFrame, wxFrame)
END_EVENT_TABLE()

Or, if you aren't goint to have any events, remove DECLARE_EVENT_TABLE(); altogether.

Try making DECLARE_EVENT_TABLE(); public instead of private.

Nah, don't do that, it's good as is. However this:

try putting this in your code:

BEGIN_EVENT_TABLE(MyFrame, wxFrame)
END_EVENT_TABLE()

Or, if you aren't goint to have any events, remove DECLARE_EVENT_TABLE(); altogether.

is indeed the answer to your problem.

Thanks, that solved it =D

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.