Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

"Undefined reference" to constructor which is defined

Tags:

c++

g++

I have a constructor whose signature is this:

cpuInput (const std::string &label);

The actual constructor uses an initialization list referencing a superconstructor, so it looks like this:

cpuInput::cpuInput (const string &label) : StateMonitor::input(label) { }

The class compiles fine as an object file. If I compile that file together with a driver that invokes the constructor:

cpuInput *cpu = new cpuInput();

Of course I get an error from g++:

demo.cpp:15:31: error: no matching function for call to ‘cpuInput::cpuInput()’
demo.cpp:15:31: note: candidates are:
In file included from demo.cpp:3:0:
input_cpusage/cpuInput.hpp:7:3: note: cpuInput::cpuInput(const string&)

Now here's the strange part: if I change the constructor call to:

cpuInput *cpu = new cpuInput("cpu");

And leave everything else the same, I now get:

demo.cpp:15: undefined reference to `cpuInput::cpuInput(std::string const&)'

I realize that const string& is not quite the same as string const&, but I had thought this was the standard way of passing a string reference (in this case, via conversion from a const char*) in C++, and this:

class A {
    public:
        A (const string &s) : x(s) { cout << x << endl; }
    private:
        const string x;
};

class B : A {
    public:
        B (const string &s) : A(s) { }
};

int main (void) {
    new B("test");
    return 0;
}             

Does NOT reproduce the issue, although it seems identical WRT the relevent elements to me.

So why on the one hand would g++ say:

candidates are ... cpuInput::cpuInput(const string&)

Then to new cpuInput("string") say:

undefined reference to `cpuInput::cpuInput(std::string const&)'

like image 456
CodeClown42 Avatar asked Aug 11 '13 14:08

CodeClown42


1 Answers

For posterity, the issue was that I defined the superclass constructor (and destructor) in a header file -- the superclass is otherwise pure virtual. No doubt this is a common C++ newbie mistake.

This means that while the derived class was compiled and linked, the superclass was not. Since the derived class was compiled as an .o the compiler did not care, but using that .o in an executable that called the derived class constructor produced the linker error:

undefined reference to subclass::subclass(...)

Although what was fundamentally undefined was superclass::superclass().

As a note, it's also necessary to compile a definition of the superclass destructor if you declare it as virtual.

like image 79
CodeClown42 Avatar answered Sep 22 '22 15:09

CodeClown42