Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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 following 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.

like image 389
GG. Avatar asked Jun 16 '10 19:06

GG.


3 Answers

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.

like image 114
mtvec Avatar answered Oct 26 '22 01:10

mtvec


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.

like image 35
Eclipse Avatar answered Oct 26 '22 01:10

Eclipse


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;
like image 43
Patrick Avatar answered Oct 26 '22 02:10

Patrick