Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Undefined reference to a derived class

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
like image 791
Jeff Avatar asked Dec 26 '22 18:12

Jeff


2 Answers

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.

like image 140
Ed S. Avatar answered Jan 07 '23 16:01

Ed S.


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()
like image 41
WhozCraig Avatar answered Jan 07 '23 14:01

WhozCraig