Reputation: 7610
I have the following code which compiled without any error or warning.
#include<iostream>
using namespace std;
class Father
{
public:
int foo()
{
cout<<"int foo";
return 111;
}
};
class Son: public Father
{
public:
long foo()
{
cout<<"long foo";
return 222;
}
};
int main()
{
Son x;
long n;
n=x.foo();
cout<<"\nn is "<<n;
return 0;
}
The Output is shown below.
long foo
n is 222
I suppose the function foo()
was overridden in the derived class Son
and not overloaded as the following program gave me errors.
using namespace std;
class Father
{
public:
int foo()
{
cout<<"int foo";
return 111;
}
long foo()
{
cout<<"long foo";
return 222;
}
};
int main()
{
Father x;
long n;
n=x.foo();
cout<<"\nn is "<<n;
}
The error message is shown below.
error: 'long int Father::foo()' cannot be overloaded
error: with 'int Father::foo()'
Both the outcomes where expected, because when two functions differ only by the return type then overriding takes place instead of overloading. But when I declared the function foo()
as virtual
in the first program, I am getting errors and I am unable to understand the reason. What rule did I violate? The program is shown below,
#include<iostream>
using namespace std;
class Father
{
public:
virtual int foo()
{
cout<<"int foo";
return 111;
}
};
class Son: public Father
{
public:
long foo()
{
cout<<"long foo";
return 222;
}
};
int main()
{
Son x;
long n;
n=x.foo();
cout<<"\nn is "<<n;
}
The error message is shown below,
error: conflicting return type specified for 'virtual long int Son::foo()'
error: overriding 'virtual int Father::foo()'
I haven't made any change other than declaring function foo()
as virtual
in class Father
. Then suddenly there arises a conflict which was absent in the first program. I am unable to comprehend this.
Any Suggestions? Thank you.
Upvotes: 1
Views: 1356
Reputation: 9097
Virtual functions whose return tipe differ from the base classes and the derived ones are allowed from the standard and are named covariant functions.
Some constraints, however, apply to the return types. Basically you are allowed to define a covariant function if it returns a pointer or a reference to a class; in this case the base class must return a pointer or a reference to a direct or indirect ancestor of the class which is returned by its sons.
References can be found, for example, here.
Upvotes: 1
Reputation: 2640
Please refer to Function overloading by return type? regarding to why return type based overloading/overriding can be problematic.
Upvotes: 2
Reputation: 9
The first example program employs the concept of overriding due to which the function defined in the derived class is called..In the virtual example program,if a function has been declared as virtual in the base class,then the function in the derived class needs to have the same signature as the base class virtual function.IN this case,the type of the function in the derived class is different due to which it gives an error.
Upvotes: 0
Reputation: 64308
When a member function is not virtual, a function with the same name in the derived class doesn't override the function in the base class, at least not in the usual sense. The derived class function merely hides the base class function. For example, if you had code like this:
Son s;
Father &f = s;
f.foo();
Then it is Father::foo()
that would be called, not Son::foo()
if Father::foo()
is not virtual.
Since Son::foo()
isn't overriding Father::foo()
, there is no special requirement that the return types match. Once you make Father::foo()
virtual however, then Son::foo()
does override Father::foo()
, and so there needs to be an agreement in the return type.
Moreover, overloading occurs when you have different argument types, not different return types. It is simply illegal to have two functions with the same name declared in the same scope that only differ by their return type.
Upvotes: 1
Reputation: 15916
You can't overload by changing the return type, only by changing the types/number of arguments to the function (or adding a const modifier, and possibly a few other ways). The reason it compiles when you do it in the derived class is because the derived one essentially hides the one from the base class.
Upvotes: 3