Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

C++ Why override method not called

I define 2 classes

class BaseA {
public:
    virtual void methodA() = 0;
};
class BaseB {
public:
    virtual void methodB(int val) = 0;
};

Child inherits 2 Base Class

class Child : public BaseA, public BaseB {
public:
    void methodA() override {
        printf("Child A\n");
    }
    void methodB(int val) override {
        printf("Child B %d\n", val);
    }
};

Then I write following code.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

void callBaseB(void *p) {
    BaseB *b = (BaseB *) p;
    b->methodB(0);
}
int main() {
    auto child = new Child;
    callBaseB(child);
    return 0;
}

console print
Child A
Why this happened? Why not call method B?

(This is what happend when a Java engineer try to write C++ code)

>Solution :

You should just do this: void callBaseB(BaseB *p) {p->methodB(0);}.

If you want to keep void *p as a parameter, you need to cast it to exactly Child * first. Either:

BaseB *b = (Child *)p;
b->methodB(0);

Or:

Child *b = (Child *)p;
b->methodB(0);

Alternatively, cast to BaseB * before converting to void *. Then casting from void * back to Base * will work.


What happens here is that the BaseB subobject is at non-zero offset inside of Child.

When you convert Child * to BaseB * (either explicitly with a cast, or implicitly, either by assigning pointers or by calling a method of BaseB on the pointer), the compiler automatically offsets the pointer by the required amount, to point to the BaseB subobject.

The offset is determined entirely at compile-time (unless virtual inheritance is involved), based on the two types.

When you obscure the source type using void *, the compiler has no way to determine the correct offset, and doesn’t even try to apply any offset, so you get weird behavior, because the resulting BaseB * doesn’t point to a BaseB instance, but rather to some junk inside of Child.

Even with virtual inheritance, despite the offset being determined at runtime, the calculation depends on the source pointer type being known.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading