C++ virtual function return type
In some cases, yes, it is legal for a derived class to override a virtual function using a different return type as long as the return type is covariant with the original return type. For example, consider the following:
class Base {
public:
virtual ~Base() {}
virtual Base* clone() const = 0;
};
class Derived: public Base {
public:
virtual Derived* clone() const {
return new Derived(*this);
}
};
Here, Base
defines a pure virtual function called clone
that returns a Base *
. In the derived implementation, this virtual function is overridden using a return type of Derived *
. Although the return type is not the same as in the base, this is perfectly safe because any time you would write
Base* ptr = /* ... */
Base* clone = ptr->clone();
The call to clone()
will always return a pointer to a Base
object, since even if it returns a Derived*
, this pointer is implicitly convertible to a Base*
and the operation is well-defined.
More generally, a function's return type is never considered part of its signature. You can override a member function with any return type as long as the return type is covariant.
C++ Overriding virtual function with different return type
In fact, this method:
virtual tErrorCode CheckThis(int id, char something);
Does not override anything, because it has a different signature from this method:
virtual bool CheckThis(int id);
Note, that you might use the override
specifier to ensure that the method in the derived class actually overrides the method of the base class.
So, this piece of code:
class Foo {
protected:
virtual bool CheckThis(int id);
};
class Bar : public Foo
{
protected:
virtual tErrorCode CheckThis(int id, char something) override;
};
Will not compile, but this one will:
class Foo {
protected:
virtual bool CheckThis(int id);
};
class Bar : public Foo
{
protected:
virtual bool CheckThis(int id) override;
};
Override virtual function with different return type
Static type checking must still hold, even if the dynamic type does something slightly different in the implementation. So it really depends on the static type of the object being pointed at. When you call the virtual member on an A*
, the return type is specified as A*
.
If you were to call it on a B*
, the return type of the function would have been (statically) a B*
.
B *obj = new B();
obj->func();
B *obj2 = obj->func(); // Okay now
Whenever you deal with run-time polynorphism in C++, it's the static type of the objects that determines the interface.
Return value of virtual functions in interface
There is no way the base class Interface
could know what distinct data type each descendant wants to return. Using different return types defeats the purpose of polymorphism. So the only way I can think to do this is to have GiveMeTheValue()
return an object type that knows what kind of value it holds, and then make that object streamable.
enum VariantType {varNull, varInt, varDouble};
struct Variant
{
VariantType Type;
union {
int intValue;
double dblValue;
};
Variant() : Type(varNull) {}
Variant(int value) : Type(varInt), intValue(value) {}
Variant(double value) : Type(varDouble), dblValue(value) {}
void writeTo(std::ostream &strm)
{
switch (Type)
{
case varNull: strm << "(null)"; break;
case varInt: strm << intValue; break;
case varDouble: strm << dblValue; break;
}
}
};
class Interface
{
public:
virtual ~Interface() {}
virtual Variant GimeMeTheValue(void) = 0;
};
class TakeInt : public Interface
{
public:
Variant GimeMeTheValue(void)
{
return Variant(10);
}
};
class TakeDouble : public Interface
{
public:
Variant GimeMeTheValue(void)
{
return Variant(3.14);
}
};
std::ostream& operator<<(std::ostream &strm, const Variant &v)
{
v.writeTo(strm);
return strm;
}
int main()
{
Interface * obj;
obj = new TakeInt();
cout << obj->GimeMeTheValue() << endl; // It's 10, thank you
delete obj;
obj = new TakeDouble();
cout << obj->GimeMeTheValue() << endl; // Oh it's 3.14, I love you c++
delete obj;
}
Returning a Derived pointer from a virtual function
When calling b->getThis()->printType(); why b->getThis returns a pointer to Base ?
Because b
is a pointer to Base
. And the type of the pointer returned by Base::getThis
is pointer to Base
.
not to Derived ?
Because Base::getThis
does not return a pointer to Derived
.
Note that while the static type of the pointer is Base
, the dynamic type is still Derived
.
Related Topics
What's the Difference Between a Header File and a Library
How to Build Qt For Visual Studio 2010
How to Use Stringstream to Separate Comma Separated Strings
Executing Cv::Warpperspective For a Fake Deskewing on a Set of Cv::Point
How to Create a Thread Pool Using Boost in C++
Remove Comments from C/C++ Code
Forward Declaration of a Typedef in C++
Why Doesn't Std::Queue::Pop Return Value.
Why No Default Move-Assignment/Move-Constructor
Is Stateful Metaprogramming Ill-Formed (Yet)
Read Numeric Data from a Text File in C++
Use 'Class' or 'Typename' For Template Parameters
Flags to Enable Thorough and Verbose G++ Warnings
Detect If Stdin Is a Terminal or Pipe