Home > database >  C cast pointer to base class pointer for virtual method call
C cast pointer to base class pointer for virtual method call

Time:03-28

I have the following code:

struct A 
{
    virtual void foo() {std::cout << "A\n";}
};

struct B : public A 
{
    virtual void foo() {std::cout << "B\n";}
};

void bar(A * a) 
{
    a->foo(); 
}

Without changing this code, is it possible to cast bp pointer to B, so calling bar would print "A"?

int main()
{
    B * bp = new B();
    bar(/* do somethig*/ bp);
    return 0;
}

Tried every cast I remebered:

int main()
{
    B * bp = new B();
    
    bar((A*)bp);
    bar(static_cast<A*>(bp));
    bar(reinterpret_cast<A*>(bp));
    bar(dynamic_cast<A*>(bp));
    return 0;
}

CodePudding user response:

You could make a shim wrapper around B, and have the shim's virtual function dispatched to BWrap::foo() call directly to A::foo();.

There's not really any point in the example to carrying along the B& member variable reference, but for more interesting examples there may be a use case.

struct BWrap : public A
{
    B& b;
    BWrap(B& bb) : b{bb} {}
    virtual void foo() { b.A::foo(); }
};

int main()
{
    B* bp = new B();
    BWrap bw{*bp};
    bar(&bw);
}

CodePudding user response:

If you insist on the A object being a base class subobject of a B object and on not modifying the first code snippet at all, then the only solution is to add an even more derived class that can override the virtual call as explained in the answer by @Eljay (which I completely forgot to think about when first writing this answer).

Other options are to create a complete A object, not a B object, or to modify bar to do a call without virtual dispatch by using a qualified name:

a->A::foo();

All of the casts you are showing have the same effect as the implicit conversion, except for reinterpret_cast which will cause undefined behavior when used this way.

  •  Tags:  
  • c
  • Related