views:

334

answers:

4

I'm getting some errors when compiling my program. They relate to the constructor and destructor of my class Instruction.

Errors are:

/tmp/ccSWO7VW.o: In function `Instruction::Instruction(std::basic_string<char, std::char_traits<char>, std::allocator<char> >, int)':
ale.c:(.text+0x241): undefined reference to `vtable for Instruction'
/tmp/ccSWO7VW.o: In function `Instruction::Instruction(std::basic_string<char, std::char_traits<char>, std::allocator<char> >, int)':
ale.c:(.text+0x2ab): undefined reference to `vtable for Instruction'
/tmp/ccSWO7VW.o: In function `Instruction::~Instruction()':
ale.c:(.text+0x315): undefined reference to `vtable for Instruction'
/tmp/ccSWO7VW.o: In function `Instruction::~Instruction()':
ale.c:(.text+0x38d): undefined reference to `vtable for Instruction'
collect2: ld returned 1 exit status

Here is my code:

//classses.h

#include <iostream>
#include <string>
using namespace std;

class Instruction{

  protected:
    string name;
    int value;

  public:
    Instruction(string _name, int _value);
    ~Instruction();
    void setName(string _name);
    void setValue(int _value);
    string getName();
    int getValue();
    virtual void execute();
};

//constructor
Instruction::Instruction(string _name, int _value){
    name = _name;
    value = _value;
}
//destructor
Instruction::~Instruction(){
    name = "";
    value = 0;
}
void Instruction::setName(string _name){
     name = _name;
}

void Instruction::setValue(int _value){
    value = _value;
}

string Instruction::getName(){
       return name;
}

int Instruction::getValue(){
    return value;
}

/////////////////////////////////////////////////////////////////////

//ale.cpp

    #include "headers.h"
    #include "functions.h"
    #include "classes.h"
    #include <list>


    using namespace std;

    int main(){

    return 0;
    }
+4  A: 

You did not define your virtual function and/or g++ wants you to make your destructor virtual (because you have virtual functions which assumes inheritance)

Dmitry
by the way, it makes no sense to assign empty strings or zeros in a destructor. Its purpose is to destroy data, not reinitialize it. In your case empty destructor is enough
Dmitry
The destructor doesn't have to be virtual (as in, it won't create a compiler error), it just should be http://www.parashift.com/c++-faq-lite/virtual-functions.html#faq-20.7
Dan Hook
That's why I put it to the second part of my reply :) I suppose that the problem is that his virtual function is not defined, but C++ compilers are so fragile species...
Dmitry
On the other hand, the destructor could be protected instead of being virtual, this would also work.
Matthieu M.
Sorry? If destructor is not virtual, then when you delete an object, you call a destructor which is specified by your variable type, not the actual type of the object. Protected destructor will not make it virtual, at best it will give a compilation error.
Dmitry
+6  A: 

I would guess the problem is due to you declaring a virtual method 'execute' in the Instruction class, and never defining it anywhere. Compilers have to produce a vtable object for a class with virtual methods and really only want one copy of it, so they usually just do it in the compilation unit (source file) that defines the first virtual function...

Chris Dodd
You were right. I didn't define the execute method.
+2  A: 

Try

virtual void execute()=0;

This will make your class abstract, which seems to be what you intend since execute isn't defined.

If you ever want to use Instruction in more than one .cpp file, you should move the implementation of the class methods into a classes.cpp file.

Dan Hook
A: 

As people already told, the problem is having execute() that is not implemented. Implement it, or make it pure virtual as says Dan Hook.

Just an extra remark: in many (maybe most depending on what you're coding on) cases, you don't need to implement the destructor. You just need if you want some specific functionnality (flushing data to a file for example).

As long as you have no pointer (as it is the case in your code), you won't have any memory tracking issues. Just remove the destructors: it's safe and it's less code. However, if only one member is a pointer, then everything gets messy and you have to deal with memory management issues, memory leaks and segfaults ;)

Tristram Gräbener
-1 If the class has any virtual members, it is more than likely that a derived class instance will be deleted through a pointer to base. In this case one definitely needs a virtual destructor too. - Its implementation can be empty, though. The string member is destroyed by having its destructor called automatically at the end of the parent destructor, and setting it to an empty string before that has no use.
UncleBens