0

So, I am trying to create a custom class, but can't figure out how to get it to work correctly. Here is what I have come up with:

message.h:

#include <errno.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fstream>
#include <string>

using namespace std;

class Message {
public:
    Message(string, string, int);
    ~Message();

    string getMessage();
    string getSubject();
    int getLength();
    void setMessage(string);
    void setLength(int);
    void setSubject(string);

private:

    string subject;
    string message;
    int length;
};

And the message.cc:

#include "message.h"

Message::Message(string Subject, string Message, int Length){
    subject = Subject;
    message = Message;
    length = Length;
}

string 
Message::getMessage(){
    return message;
}

void
Message::setMessage(string Message){
    message = Message;
}

string 
Message::getSubject(){
    return subject;
}

void
Message::setSubject(string Subject){
    subject = Subject;
}

int 
Message::getLength(){
    return length;
}

void
Message::setLength(int Length){
    length = Length;
}

Here is what I am trying to do:

map<string,vector<Message> > database;

string request = get_request(client);
//store the request in memory
vector<Message> messageList = database.at("user1");
messageList.push_back(new Message("subject", request, request.size()));
database["user1"] = messageList;

This code gives the following compile errors(because I am creating a new message):

//no known conversion for argument 1 from Message* to const Message&

But when I change the code to be:

//store the request in memory
vector<Message> messageList = database.at("user1");
Message message;
message.setMessage(request);
message.setSubject("subject");
message.setLength(request.length());
messageList.push_back(message);
database["user1"] = messageList;

it gives the following errors for Message message:

//No matching function for call to Message::Message()
//candidates are: 
//Message::Message(str::string, str::string, int)
//Message::Message(const Message&)
//candidate expects 3 and 1 arguments, 0 provided

So, this leads me to believe that I am missing something in my message class (or header) that would allow for this type of instantiation, but I don't know how to do this or what I am missing. Any help would be really appreciated. I only have a very basic understanding of C++ since I have mostly programmed in Java, but no matter how much I try to look up the errors I get or code it in a different way I am not successful at compiling the code. Thanks again.

fudge22it
  • 103
  • 1
  • 2
  • 13
  • If you're used to Java, you're probably used to all objects automatically being treated as references (a la the `Integer` class vs the `int` primitive type). C++ has no such magic. `new` returns a pointer. [This question on SO](http://stackoverflow.com/questions/57483/what-are-the-differences-between-a-pointer-variable-and-a-reference-variable-in?rq=1) may be a good starting point for further reading. – Dan Sep 22 '14 at 03:35

3 Answers3

1

Change messageList.push_back(new Message("subject", request, request.size())); to:

messageList.push_back(Message("subject", request, request.size()));

You have a vector of Messages (which manages its own memory), not a vector of pointers to memory that you manage.

Equivalently you could write:

Message message("subject", request, request.size()));
messageList.push_back(message);

Your attempt with Message message; failed because you don't have a default constructor.

In C++11 you can also write:

messageList.emplace_back("subject", request, request.size());

Other things:

  • The third argument (Length) is redundant as the message could just do message.size() when it needs to know that.

  • database["user1"] = messageList; will overwrite the vector already in the map; if you want to add onto the vector in the map then get rid of messageList and do database["user1"].push_back("subject", request, request.size());

M.M
  • 138,810
  • 21
  • 208
  • 365
  • Thanks for pointing out the redundancy. I will probably get rid of that third parameter. – fudge22it Sep 22 '14 at 03:35
  • Yeah, when I do it this way, the compiler says undefined reference to 'Message::~Message()' – fudge22it Sep 22 '14 at 03:44
  • You declared the destructor `~Message();` but have not written the body for it yet. (Actually your class does not require any manual cleanup of resources, since `string` cleans itself up, so you could just remove that declaration) – M.M Sep 22 '14 at 03:46
  • Yeah, now I am getting undefined reference to 'Message::Message(std::basic_string,std::char_traits, std::allocator >, int)' – fudge22it Sep 22 '14 at 03:51
  • As before, you need to define that function. You declared it in the class definition and never provided a function body. (That message refers to a function that was not declared in the code you actually posted, you only posted `Message(string, string, int);`. That error message says that you declared a constructor `message(string, int)`). – M.M Sep 22 '14 at 03:52
  • Isn't that the first thing I do in the message.cc file as I posted above? Or is there something I am not understanding? – fudge22it Sep 22 '14 at 03:54
  • No, that is the definition of `Message(string, string, int)`. That's a different function to `Message(string, int)`. – M.M Sep 22 '14 at 03:54
  • Yeah, it looks like I read the error message wrong, it was undefined reference to 'Message::Message(std::basic_string, std::char_traits, std::allocator >, std::basic_string, std::char_traits, std::allocator >, int)' which supposedly what I had written at the beginning of the message.cc file. This has me stumped. – fudge22it Sep 22 '14 at 04:41
  • @fudge22it perhaps you are not actually linking `Message.cc`'s object file with your main function's object file. At any rate, this is a completely separate issue to what you were originally asking about so you should post a new question, and also make a *minimal* example that reproduces it. All your vector code is unrelated, you just need to create a `Message`. – M.M Sep 22 '14 at 04:44
0

The problem is here:

vector<Message> messageList = database.at("user1");
messageList.push_back(new Message("subject", request, request.size()));'

Your messageList is a vector containing Message class instances. The new operator returns a pointer to a class, so you're attempting to push a pointer to Message instead of a Message class instance.

Depending on what you want to do, you could use either a vector of Message class instances, or a vector of pointers to Message class instances, neither approach is wrong, or right, it all depends on what it wants to do.

Sam Varshavchik
  • 114,536
  • 5
  • 94
  • 148
-1

It seems you have a variety of problems. One of them is that you need a default constructor which is being invoked when you do:

Message message;

Adding this will probably suffice:

Message::Message(){
}

and the corresponding declaration in the .h

carlosdc
  • 12,022
  • 4
  • 45
  • 62