4

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
Community
  • 1
  • 1
Jeff
  • 4,285
  • 15
  • 63
  • 115
  • 3
    Please post real code "private void Derived::quickSort()` isn't valid. C++ isn't Java. Also, post **minimal** code. Problems with constructors and destructors typically don't need all the stuff that's in derived.cpp, and I had to scroll through it several times to see that `Derived::Derived(int)` is not defined. – Pete Becker Sep 07 '12 at 22:39
  • Terribly sorry about all the code... I wasnt sure what would be needed. – Jeff Sep 07 '12 at 22:47
  • Please include Base.cpp, as you included Base.h twice in your source lists; once for Base.h, and again for base.cpp. Only then can we see if Base::~Base() is properly defined (and it better be, since it is declared in the header. – WhozCraig Sep 07 '12 at 22:48
  • Note that, with your new edit which includes a destructor definition, you have now broken [The Rule of Three](http://en.wikipedia.org/wiki/Rule_of_three_(C%2B%2B_programming)) and are sure to run into a segfault (hopefully!) sometime soon. – Ed S. Sep 07 '12 at 23:27
  • This is where I am a bit confused -- I have defined all three, but since they are virtual, my inherited class has to define them again, right? – Jeff Sep 07 '12 at 23:36
  • @Jeff: No, it doesn't *have to* define them unless it is a pure virtual function, i.e., `virtual void foo() = 0`. However, if the function is ever going to be called, *someone* needs to define it. In the case of a destructor that is marked virtual at the base class, it needs to be defined in each because the call chain will walk up the inheritance hierarchy, calling each in turn. – Ed S. Sep 07 '12 at 23:46
  • @Jeff: Per your edit; you *declared* a destructor in `Derived`, you did not *define* it. You must do both, as my example explained. – Ed S. Sep 07 '12 at 23:47
  • @Jeff How are you compiling your program? Are you using an IDE, such as Visual C++, or are you using a command-line compiler? – Code-Apprentice Sep 08 '12 at 18:44

3 Answers3

8

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.

Ed S.
  • 122,712
  • 22
  • 185
  • 265
  • 1
    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. – WhozCraig Sep 07 '12 at 22:50
  • @CraigNelson: True, I'm assuming based upon this: `undefined reference to Base::~Base()'` – Ed S. Sep 07 '12 at 22:53
  • @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. Sep 07 '12 at 23:25
  • 1
    @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` – Ed S. Sep 07 '12 at 23:28
  • I made it a bit simpler, I think. – Jeff Sep 07 '12 at 23:45
3

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()
WhozCraig
  • 65,258
  • 11
  • 75
  • 141
0
main.cpp:(.text+0x15): undefined reference to `Derived::Derived(int)'

This error message doesn't say an undefined reference to a class as the question of your title says. Rather it is complaining about an undefined reference to a constructor which takes an int parameter. From my cursory look at your code, you have only declared this constructor and not defined it. Add a definition to your .cpp file and you should solve this error.

Also, it is common practice to place constructor declarations before all member function declarations. At first I missed these declarations because they weren't where I expected. I strongly suggest that you do this to help avoid future misunderstandings when you ask questions here.

Code-Apprentice
  • 81,660
  • 23
  • 145
  • 268
  • 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. – WhozCraig Sep 08 '12 at 00:13
  • @CraigNelson My bad. As with the .h files, I was looking for constructors at the top, not the bottom. ;-( – Code-Apprentice Sep 08 '12 at 00:17
  • @Code-Curu I was in the same boat for the first 5 minutes of staring at it, so you're not alone. – WhozCraig Sep 08 '12 at 00:28
  • I could post all the code... it would be ridiculously large though... Should my .h files be done differently? – Jeff Sep 08 '12 at 00:33
  • 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. – WhozCraig Sep 08 '12 at 00:47
  • @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. – Code-Apprentice Sep 08 '12 at 18:41