Rakesh K
Rakesh K

Reputation: 8515

Adding item to list in C++

I am using two classes in my C++ application. The code is as follows:

class MyMessageBox
{
public:
    void sendMessage(Message *msg, User *recvr);
    Message receiveMessage();
    list<Message> dataMessageList;
};

class User
{
public:
    MyMessageBox *dataMsgBox;
};

The msg is a pointer to a derived class object of Message class. I have implemented the function sendMessage as follows:

void MyMessageBox::sendMessage(Message *msg, User *recvr)
{
    Message &msgRef = *msg;
    recvr->dataMsgBox->dataMessageList.push_back(msgRef);
}

When I compile this code, I get the following error: undefined reference to `vtable for Message'. Please help me out to solve this issue.

Thanks, Rakesh.

Upvotes: 0

Views: 3286

Answers (5)

stefaanv
stefaanv

Reputation: 14392

As some are proposing better solutions: check out std::queue or std::deque to queue your messages. So now you have:

std::queue<std::tr1::shared_ptr<Message> > dataMessageQueue;

Upvotes: 0

Jon Cage
Jon Cage

Reputation: 37500

I think this is a slightly contrived error message suggesting that you've not implemented a constructor for your message class. Have a look here and here on SO...

Given that you're trying to pass a pointer to a list of objects, the compiler is probably complaining that it has no way to convert Message* to Message. Try changing your list to a list of Message* as Kylotan suggests.

Is it a compile or a link error?

Upvotes: 0

Timo Geusch
Timo Geusch

Reputation: 24351

For starters, if you want to store a polymorphic object in a standard C++ container, you should store a pointer to the object and not an object of the base class. If you don't, you run into object slicing issues. Also, do yourself a favour and wrap the pointer in a smart pointer to prevent resource leaks - I would recommend boost::shared_ptr<>.

Given that you haven't shown us the code for Message, we can but guess what the problem is. As it's referring to a vtable, chances are that:

  • You didn't declare any of Message's class members as virtual. Starting with the destructor would be a good idea
  • You forgot to link against an object file that contains the compiled code for Message

By the way, creating the additional reference in sendMessage() is not necessary and IMHO doesn't exactly help readability. Just dereference the msg pointer in your call to push_back().

Upvotes: 1

Kylotan
Kylotan

Reputation: 18449

I don't know what you're trying to do with that msgRef, but it's wrong. Are you an ex-Java programmer, by any chance?

If Message is a base class for derivatives of Message, you need to store pointers in the list. Change list<Message> to list<Message*>; and push_back(msgRef) should become push_back(msg), removing the msgRef code entirely.

Also, as a matter of style, it's a bad idea to chain lots of -> operators together. It's better to implement a method on User in this case that adds a Message to its own list and call that.

Upvotes: 4

Pontus Gagge
Pontus Gagge

Reputation: 17258

If you want to handle subclassed Messages, you need to use a list of Message pointers rather than Message objects, and manage their lifetime. For convenience, I'd suggest making it

list< boost::shared_ptr<Message> > datamessageList

using the boost library. (And not to offend, but you do need to read up a bit more on C++ and pointers: it looks like you tried various permutations of your code until you got something that compiled...)

Upvotes: 0

Related Questions