开发者

Using const_iterator when overloading a const operator[]

I really do not understand what I am doing wrong below. I have a class named Settings with the structure listed below, and two of the functions listed below as well. What I am having trouble with is specifically where to put the const modifiers when overloading a const operator[] within the overloading function. Do I need to use const_cast somewhere? What am I missing?

class Settings
{
    map<string, string> settingsMap;
    map<string, string>::const_iterator itc;

    const string getValue(string) const;

    public:
    const string operator[](string) const;
};

const string Settings::operator[](string K) const
{
    return getValu开发者_JS百科e(K);
}


const string Settings::getValue(const string K) const
{
    const map<string, string> m = settingsMap;
    itc = m.begin();
    while(itc != m.end())
    {
        if(itc->first==K)
            return itc->second;
        itc++;
    }
    return 0;
}

Thanks in advance.


Your problem is not with the const but with references.
Also your declarations in the class must match exactly the definitions you use when defining the functions.

class Settings
{
    map<string, string> settingsMap;
    map<string, string>::const_iterator itc;

    const& string getValue(const string& K) const; 
               //          ^^^^^  Added const to match definition below.
               //                 Also note the reference. This means you are referring
               //                 to the original value but because the reference is const
               //                 it cant be modified via this reference.

// ^^^^^^  This const means the returned value is const.
//         unless you return a reference this is meaningless. 
//         So also note the reference here are well.

                                 //         ^^^^^^  The last const means the method will
                                 //                 NOT change the state of any members. 

    public:
    const string&  operator[](const string&) const;
//  ^^^^^^^^^^^^^ As above return a const reference.
                          //  ^^^^^ As above pass parameters by const reference
                          //        otherwise it makes a copy of the parameter.
                                      //     ^^^^^  function will not change any members.
};

const string& Settings::operator[](const string& K) const  // Must match above definition.
{
    return getValue(K);
}


const string& Settings::getValue(const string& K) const
{
    const map<string, string> m = settingsMap;
//  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ As this is an object (not a reference)
//                                You are making a copy of the object into a local variable.
//                                This is probably not what you want.

    const map<string, string>& m = settingsMap; // This works.

    itc = m.begin();


    while(itc != m.end())
    {
        if(itc->first==K)
            return itc->second;
        itc++;
    }

    return 0;
 // ^^^^^^^^  This is not a good idea.
 //           It is creating a string from a NULL pointer (0 is convertible to pointer).
 //           What you really wanted to do is return a string. This is also why your
 //           return type was not working as you expected.

     static const string emptyResult;  // create a static object to use as the empty result
     return emptyResult;
}


If your function getValue() modifies the member itc, then it can't be const (unless itc is mutable). I suggest you declare itc in the function getValue():

...
const map<string, string> m = settingsMap;
imap<string, string>::const_iterator itc = m.begin();
...


the operator[] in c++ has two meanings:
(1) a[i] = x; //store x into a in position i
(2) x = a[i]; //load a in position i to x

The first one must change the structure... and thus the structure cannot be const, so you should drop the last const for this: const string operator[](const string); [note that the parameter in here is const string and not string, since it should probably not be changed. in addition, since the output string shouldn't probably be changed, it should be defined as const as well.

The 2nd one, should probably return a string, and not a const string, so you should probably drop the first const: string operator[](const string) const; [since the original structure for this op is not changed, the last const is good and should remain]. In addition note the parameter is a const string and not a string, since you do not want to cahnge the parameter.

In your case: It seems you want the 2nd meaning for the operator[], thus you should declare it as: string operator[](const string) const;


In your declaration:

const string operator[](string K) const;

if you want just to read (and copy) the contents of the map, then the correct declaration should be:

const string operator[](const string &k) const;

The return type should be const, otherwise you may be able to modify a temporary value, and this is not correct. The argument can be passed by const reference, since you are not modifying it. With this declaration, the following two lines of code will give you an error:

...
s["abc"] = "cde";   // cannot modify, the return type is const
s["abc"] += "efg";  // cannot modify, the return type is const

The const after the prototype declaration just tell you that operator[] does not modify the object, so it has to do with the code inside the method operator[], and not about its usage. For this reason, the const_iterator should be defined as local variable inside operator[] code.

The const on the return type avoids the possibility that you modify a temporary value (the return type). For efficiency, you can obtain the same result by returning a const reference.

const string& operator[](const string &k) const;

Of course, if you want to modify the Settings container with operator[], then you should return a non const reference.

string& operator[](const string &k);
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜