Undefined reference to a derived class

11,773

Solution 1

You have declared a virtual destructor in Base, yet you never define it. It needs to be defined in Derived (as well as in Base because it is not a pure virtual function) because it will be called once main exits. You should have:

class Base {
public:
    // ...
    virtual ~Base();
};

Base::~Base() {}

class Derived : public Base {
public:
    // ...
    ~Derived();
};

Derived::~Derived() { /* whatever */ }

That is the cause of at least one of your errors. I don't know if this one is a red herring or not, but it seems to be:

/tmp/ccw1aT69.o: In function main': main.cpp:(.text+0x15): undefined reference toDerived::Derived(int)'

You define Derived::Derived(int), so it's hard to imagine that is a real error. Define your destructor and see if it goes away.

Solution 2

Ok, just for clarity, and since I can't put formatted code in anything besides an answer. You do NOT need to provide a destructor in a derived class just because your base class has a virtual dtor or pure methods. The following is about as simple as I can get to demonstrate this in three different construct/destruct conditions. the output is listed after the code. I hope this at least helps @Jeff. I tested this under VS2005/2008/2010 and an ancient gcc 4.1.2, so it better be right.

#include <iostream>

class Base {
public:
    Base()
        { std::cout << "Base()" << std::endl; };

    virtual void call_me() = 0;

    virtual ~Base()
        { std::cout << "~Base()" << std::endl << std::endl; };
};

class Derived : public Base {
public:
    Derived(int i=1)
        { std::cout << "Derived(" << i << ")" << std::endl; }

    // Base::call_me requirements.
    void call_me() 
        { std::cout << "call_me()" << std::endl; }
};

int main(int argc, char* argv[])
{
    // use derived class pointer type
    Derived* pDerived = new Derived();
    pDerived->call_me();
    delete pDerived;

    // use base class pointer type
    Base* pBase = new Derived(2);
    pBase->call_me();
    delete pBase;

    // scope based
    {
        Derived obj(3);
        obj.call_me();
    }
    return 0;
}

The output for this is:

Base()
Derived(1)
call_me()
~Base()

Base()
Derived(2)
call_me()
~Base()

Base()
Derived(3)
call_me()
~Base()
Share:
11,773
Jeff
Author by

Jeff

Updated on June 22, 2022

Comments

  • Jeff
    Jeff almost 2 years

    EDIT: RELATED TO c++ undefined reference to `vtable

    I am trying to do a project on inheritance and I'm getting this error:

    /tmp/ccw1aT69.o: In function `main':
    main.cpp:(.text+0x15): undefined reference to `Derived::Derived(int)'
    /tmp/ccw1aT69.o: In function `Derived::~Derived()':
    main.cpp:(.text._ZN20DerivedD2Ev[_ZN20DerivedD5Ev]+0x13): undefined reference to `vtable for Derived'
    main.cpp:(.text._ZN20DerivedD2Ev[_ZN20DerivedD5Ev]+0x1f): undefined reference to `Base::~Base()'
    collect2: ld returned 1 exit status
    

    This is my code:

    main.cpp:

    #include <iostream>
    #include "Base.h"
    #include "Derived.h"
    
    int main() {
        Derived intList(25);
    }
    

    base.h:

    #ifndef BASE_H
    #define BASE_H
    
    class Base {
        public:
                ...
                Base (const Base& otherList);
                virtual ~Base();
        protected:
                int *list;
                int length;
                int maxSize;
    };
    
    #endif
    

    Base.cpp:

    #include "Base.h"
    #include <iostream>
    
    using namespace std;
    
    ...definitions of my members...
    
    Base::Base (int size) {
    //stuff
    }
    Base::~Base() {
        delete [] list;
    }
    Base::Base (const Base& otherList) {
    //stuff
    }
    

    Derived.h:

    #ifndef DERIVED_H
    #define DERIVED_H
    #include "Base.h"
    
    class Derived: public Base {
        public:
                 ...
                Derived (int size = 100);
                ~Derived(); //THIS LINE ADDED AFTER FIRST ANSWER
    };
    
    #endif
    

    Derived.cpp:

    #include "Derived.h"
    #include <iostream>
    
    using namespace std;
    
    Derived::Derived (int size)
            :Base(size){
    }
    

    What causes this error? It looks like I can't call the constructor, but it looks fine to me.

    EDIT: I tried the first solution. Error now:

    /tmp/ccA4XA0B.o: In function `main':
    main.cpp:(.text+0x15): undefined reference to `Derived::Derived(int)'
    main.cpp:(.text+0x21): undefined reference to `Derived::~Derived()'
    collect2: ld returned 1 exit status
    
  • WhozCraig
    WhozCraig over 11 years
    I concur, but without seeing Base.cpp lord knows what is implemented and what isn't. But Derived::~Derived() doesn't have to be declared+defined; it can be neither (not present at all). The compiler will generate a default version if you don't, and it will be virtual since the base class is (Base::~Base()). But we need the base.cpp file.
  • Ed S.
    Ed S. over 11 years
    @CraigNelson: True, I'm assuming based upon this: undefined reference to Base::~Base()'
  • Ed S.
    Ed S. over 11 years
    @Jeff: I see no mention of orderedArrayListType anywhere in your code. Using my solution to problem #1 I would think you may be able to reason out the cause of problem #2
  • Ed S.
    Ed S. over 11 years
    @Jeff: I left a comment on your post. You posted your destructor implementation and it has a problem. Instances of your class cannot be copied without running into a double delete
  • Jeff
    Jeff over 11 years
    I made it a bit simpler, I think.
  • WhozCraig
    WhozCraig over 11 years
    It is no longer in the source base, but Derived::Derived(int) is defined at the bottom of the Derived.cpp file. This, people, btw, is the primary reason why it is SO preferred you post the actual code that is causing problems and do so with completeness. if that is simply too complicated, then a sample that exhibits the SAME PROBLEM will suffice.
  • Code-Apprentice
    Code-Apprentice over 11 years
    @CraigNelson My bad. As with the .h files, I was looking for constructors at the top, not the bottom. ;-(
  • WhozCraig
    WhozCraig over 11 years
    @Code-Curu I was in the same boat for the first 5 minutes of staring at it, so you're not alone.
  • Jeff
    Jeff over 11 years
    I could post all the code... it would be ridiculously large though... Should my .h files be done differently?
  • WhozCraig
    WhozCraig over 11 years
    It wasn't the .h that was turning heads, it was the .cpp file. One normally doesn't expect to find a constructor at the bottom. Nothing wrong with it, just a little odd. Has caused more than one person to suggest the constructor was undefined only because they didn't expect to find it at the bottom of the implementation file. Tomato/Tomato.
  • Code-Apprentice
    Code-Apprentice over 11 years
    @Jeff I suggest putting your constructors at the top of both the class declaration in the .h file and at the top of the .cpp file.