Can overloading is possible with two version of function, constant member function and function without const
I just came across various overloading methods like type of parameter passed, varying number of parameters, return type etc. I just want to know that can I overload a function with fo开发者_C百科llowing two version
//function which can modify member String& MyClass::doSomething(); //constant member function String& MyClass::doSomething() const;
Please let me know the reason behind it.
Yes you can.
If you have
MyClass m;
m.doSomething();
The non-const version will be called. When you have
const MyClass m;
m.doSomething();
The const version will be called.
The easy way to understand this, is to think of the object you are calling the method on as the 0th parameter:
e.g.: Think of
String& MyClass::doSomething();
MyClass mc;
mc.doSomething();
as a fancy, compiler supported way of doing this:
String& MyClass_doSomething(MyClass *this);
MyClass mc;
MyClass_doSomething(&mc);
Now, overloading based on constness is just a special case of overloading by parameter types:
String& MyClass::doSomething();
String& MyClass::doSomething() const;
can by thought of as something like this:
String& MyClass_doSomething(MyClass *this);
String& MyClass_doSomething(const MyClass *this);
As to the usefullness of this, the easiest examples are the begin
and end
methods on various std::
containers. If the vector
/string
/whatever is non const, and you call begin()
, you'll get back an iterator
that can be used to modify the contents of the original container. Clearly, this shouldn't be allowed for containers marked const
, so, thanks to the const/non const overloading, calling begin()
on a const vector return a const_iterator
that can be used to read the contents of the vector, but not modify it.
e.g.
string nc = "Hello world";
for (string::iterator iString = nc.begin(); iString != nc.end(); ++iString)
{
cout << *iString;; // legal to read
*iString = toupper(*iString); // legal to write
}
const string c = "Hello world again";
for (string::const_iterator iString = c.begin(); iString != c.end(); ++iString)
{
cout << *iString;; // legal to read
// *iString = toupper(*iString); // Writing is illegal
}
As to overloading by return type, you can't do it in C++. However, you can simulate it fairly decently.
Yes, you can do this. (@Job, this is not overload on return type, this is overload on 'const-state' of the called class instance)
If the instance is const, the second variant will be called, if it isn't, the first one is called. The practical use is that if the method is called on a const instance, you probably also want to return a "const String&" (e.g. if you return a reference to a member of the class), like this:
//function which can modify member
String& MyClass::doSomething();
//constant member function
const String& MyClass::doSomething() const;
This is how iterator is used. You have a const iterator as well as a non-const one.
Not only is this possible, it as a commonly used idiom.
For example, if the const
version of a function is called, a reference to a read-only version of a result can be returned. But if the non-const
version is called, a copy is constructed and returned that the receiver may modify. By implementing a const
version, we are saved from performing the construction when we know it isn't going to be needed.
精彩评论