Virtual method with different return type

Started by
5 comments, last by Jaiminho 16 years, 11 months ago
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)
Advertisement
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.
"We should have a great fewer disputes in the world if words were taken for what they are, the signs of our ideas only, and not for things themselves." - John Locke
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.
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();};
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.
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.
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.

This topic is closed to new replies.

Advertisement