简体   繁体   中英

c++ string manipulation in setter

Can I manipulate string in setter? For example I want to set it length to 20. Is it that possible and is it the best practice? I get "Non const function is called on const object". Code tried:

void setName(const string &name) {
    if (name.size() > 20)
    {
        name.reserve(20);
    }
    Employee::name = name;
}

No, in your example name is a const string reference so you can only use const methods on it (basically meaning you can't modify name ). The reserve is not a const method. The const string& name means that name is the same string as the caller supplied, the const means that you may not modify it.

What you could do however is to create a copy of name somehow. The most obvious way is maybe to create a copy inside the method, this means that you can keep the function signature (which may be a good thing IMHO):

void setName(const string &name) {
    string tname = name;
    if (tname.size() > 20)
    {
        tname.reserve(20);
    }
    Employee::name = tname;
}

Another way you could do it is to pass name by value which means that the argument will be a copy of what was supplied by the caller (one could argue that one shouldn't alter the signature of the method to reflect the implementation, but that's a matter of opinion):

void setName(string name) { // note no ampersand

What you can't / shouldn't do is to only remove the const because that would mean that the argument is the same string as the caller supplied. It will fail to compile if the caller don't supply a mutable name and if supplied a mutable name the callers copy would change as well (since it's the same).

It seems to me that you are addressing the problem in the wrong way. The code posted calls reserve when the size of the string passed is higher then 20, but that is a non-binding request to shrink the string (which is const, BTW).

If you want to limit that string member of your class to a particular size while passing a const reference in a setter, all you have to do is copying into it only a substring of the passed string.

I get "Non const function is called on const object"

Of course. That's the whole point of const in the first place!

 if (name.size() > 20) { name.reserve(20); } 

This does not make sense at all. It literally says: "If the string has more than 20 characters, then make sure that it can internally hold at least 20 characters" .

Now, the call may also have the effect that the string's internal capacity shrinks to whatever size greater than 20 it represents to the outside world. For example, if your string has size 30 and its current capacity is 1000, then reserve(20) may shrink the capacity to 30.

However, this is a low-level memory-management concern a beginner typically doesn't or shouldn't care about. If, what I believe, your intention is merely to cut the string, then you need resize .

I would solve your problem like this, plain and simple:

void setName(std::string const& name)
{
    this->name = name;
    if (this->name.size() > 20)
    {
        this->name.resize(20);
    }
}

You cannot mutate const references: this means that you will not be able to call std::string::reserve as it's not const -qualified.

Consider taking name by value:

void setName(string name) 
 {
    if (name.size() > 20)
    {
        name.reserve(20);
    }

    Employee::name = name;
}

In this case, a copy of the string passed to setName will be made, which can be mutated leaving the original unchanged.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM