0

I've got the code:

string key = "", value = "", type = "";
while(in)
{
    getline(in, key, '=');
    getline(in, value, '\n');
    getline(in, type, '\n');
    in.get(); // get the dividing empty line
    CommonParamValue *paramValue = CreateParamValue(type);
    paramValue->SetValue(value);
    params.insert(make_pair(key, *paramValue)); // PROBLEM
    delete paramValue;
}

When I call params.insert(make_pair(key, *paramValue)); I get an element of map with correct key end EMPTY value. When I check

paramsIter = params.find(paramKey);
    if (paramsIter != params.end())
    {
        if( ("" == paramsIter->second.GetValue())
        ...
    }

All the time condition "" == paramsIter->second.GetValue() is true, but it must not be so! Additional information:

class CommonParamValue
{
public:
    virtual void SetValue(string value){}
    virtual string GetValue(){ return ""; }
};
class StringParamValue : public CommonParamValue
{
    string str;
public:
    StringParamValue(){}
    virtual void SetValue(string value){str = value;}
    virtual string GetValue() {return str;}
};
CommonParamValue* Report::CreateParamValue(const string &strType) const
{
    if (strType == "int")
    {
        return (new IntParamValue());
    }
    else if(strType == "string")
    {
        return (new StringParamValue());
    }
    else
    {
        // error
        exit(1);
    }
}

The question is why when I do params.insert(make_pair(key, *paramValue)); I always get an element with correct key and an EMPTY value? What is wrong?

Sergey Shafiev
  • 4,205
  • 4
  • 26
  • 37
  • 1
    You have encountered something called _slicing_. See e.g. the answers to [this question](http://stackoverflow.com/questions/274626/what-is-the-slicing-problem-in-c) for some more information. – Some programmer dude Jun 20 '12 at 09:30
  • Polymophism always does its trick by a pointer, not by an object! What you have done is inserting an object with a type of CommonParamValue into a stl map, so all the additinal information in StringParamValue is lost! – Gang YIN Jun 20 '12 at 09:35
  • Maybe you should declare params as std::map, so you can just call params.insert(make_pair(key, paramValue)), of course, you should delete that object lately when you're sure it won't be used anymore. – Gang YIN Jun 20 '12 at 09:37

2 Answers2

3

I suspect the map is declared as:

std::map<std::string, CommonParamValue> params;

The insertion will result in the slicing of the value, to a CommonParamValue which always returns a "" from GetValue(). To obtain the desired behaviour the value would in the map would need to be a pointer to a CommonParamValue, preferably a smart pointer:

std::map<std::string, std::shared_ptr<CommonParamValue> > params;
hmjd
  • 120,187
  • 20
  • 207
  • 252
0

The object inserted into the map is a CommonParamValue not a StringParamValue, that means that the copy of your objects inserted into the map get sliced to CommonParamValue.

Change your map definition to have a (smart) pointer or reference mapped.

Antonio Pérez
  • 6,702
  • 4
  • 36
  • 61