Sign in to follow this  
Jaiminho

Virtual method with different return type

Recommended Posts

Is there any way to do something like that? Simply doing it this way gets me a compiling error, obviously. Is there a way to achieve this without breaking any rules? Something that worked like:
class Super
{
  public:
    virtual int f() { ... }
};

class Sub : public Super
{
  public:
    float f() { ... }  // obvious error
};

This would be used for code simplification. Turning this:
{
    Super *p;

    // stuff happens with p

    if(typeid(*p) == typeid(Sub1)) {
        Sub1 *s = static_cast<Sub1*>(p);

        s->do_stuff();
    }
    else if(typeid(*p) == typeid(Sub2)) {
        // and so on
    }
}

Into this:
{
    Super *p;

    // stuff happens with p

    p->info().do_stuff();
}

Method do_stuff() would be virtual from the superclass. Calling info()->do_stuff() would call the subclass method. I want that code to work as if p->info() returned a reference (or pointer) to the proper subclass. I can do this using preprocessor macros, but I would need to modify it every time I create a new class inheriting Super. Any ideas? (maybe this is not a type safe code, so I'm probably kinda doing wrong stuff)

Share this post


Link to post
Share on other sites
You can do this, but only when the return types are covariant, i.e., when the overridden function's return type is derived from the original function's return type, and the types are either pointers or references. (I don't think it would work with just values, only pointers/references. Otherwise, you could cause slicing, as best I can figure.)

It is an annoying note that this does not work with smart pointers, even though smart pointers do a decent job of dealing with base/derived relations in other cases.

Share this post


Link to post
Share on other sites
Make the do_stuff method virtual. In the code you're trying to simplify, it looks like you're just using run-time type information when you could just call a virtual method.

Share this post


Link to post
Share on other sites
You cant do that but you can do this:

struct ret_base { };
struct ret_derived : public ret_base { };

struct base
{
virtual ret_base& do_stuff();
};

struct derived : public base
{
virtual ret_derived& do_stuff();
};



Share this post


Link to post
Share on other sites
Quote:
Original post by Vorpy
Make the do_stuff method virtual. In the code you're trying to simplify, it looks like you're just using run-time type information when you could just call a virtual method.


Would be that simple, yes, but that was just an example. I need to use some members that super class doesn't know about and can't do that simply with virtual methods.

------------------

Ok... it shows no error on method, but does on usage:


class Super
{
public:
virtual ~Super() { }

virtual Super& f() { return *this; }
};

class Sub : public Super
{
public:
virtual ~Sub() { }

virtual Sub& f() { return *this; }

int x;
};


int main()
{
Super *s = new Sub;

s->f().x(); // Error here: class Super has no member x

return 0;
}





I'm on GCC, BTW. Doing some console output inside f() gets me what I tell to print in Sub's method. This is strange.

Share this post


Link to post
Share on other sites
Quote:
Original post by Jaiminho
Quote:
Original post by Vorpy
Make the do_stuff method virtual. In the code you're trying to simplify, it looks like you're just using run-time type information when you could just call a virtual method.


Would be that simple, yes, but that was just an example. I need to use some members that super class doesn't know about and can't do that simply with virtual methods.

------------------

Ok... it shows no error on method, but does on usage:

*** Source Snippet Removed ***

I'm on GCC, BTW. Doing some console output inside f() gets me what I tell to print in Sub's method. This is strange.


The problem is quite clear, you are trying to retrieve member "x" from an object of type "Super", which declares no such member. Remember that such type checking is done at compile time, C++ doesn't even take into consideration the fact that the return value may be of a derived type. What the C++ compiler sees is:

0) I have a Super object pointer
1) I call f() on it
2) according to class Super{}; that returns a Super reference
3) Now lets get its member x... wait a minute, a super doesn't have a "x"... error and die

I think it would be better for you to explain to us what you are actually trying to do, because there may be a better way to go about it.

Share this post


Link to post
Share on other sites
I'm implementing an event system using inheritance, to avoid unions and such, so I have structures with some data that doesn't belong to the super, but I want to access it through a "cleaner" (and maybe faster .. /shrug) way than static_casting and such.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this