c++multiple-inheritancecovariance

covariant return types with multiple inheritance. how does this code work?


Can anyone tell me how does return type covariance work in the following code?

class X
{
public:
    int x;
};

class Y: public OtherClass, public X
{
};


static Y inst;

class A {
public:
    virtual X* out() = 0;
};

class B : public A
{
    public:
    virtual Y* out() 
    {
         return &inst;
    }
};



void main()
{
    B b; 
    A* a = &b;
    //x and y have different addresses. how and when is this conversion done??
    Y* y = b.out();
    X* x = a->out();
}

EDIT: I'm sorry I must not have been clear enough. x and y point to different addresses just like I expect since there's multiple inheritance involved so X and Y objects are not on the same address. My question is when is this cast being done? the out() function couldn't have done this because it always returns a pointer to Y from its point of view. The caller of out() couldn't have done this because it sees X* whose concrete type might be X or Y. When is the cast done then?


Solution

  • By "how does it work", I presume you're asking about what the generated code looks like. (In a typical implementation, of course. We all know that the generated code can vary somewhat between implementations.) I'm aware of two possible implementations:

    The compiler always generates code to return a pointer to the base class; i.e. in B::out, the compiler will convert the Y* to an X* before returning it. At the call site, if the call was through an lvalue with static type B, the compiler will generate code to reconvert the returned value to Y*.

    Alternatively (and I think this is more frequent, but I'm far from sure), the compiler generates thunks, so when you call a->out, the virtual function which gets called is not directly B::out, but a small wrapper which converts the Y* returned from B::out to an X*.

    Both g++ and VC++ seem to use thunks (from a very quick glance).