C++ Virtual Function Return Type

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



Leave a reply



Submit