0

Considering a class "A", its subclass "B" and a function "f". The function "f" calls a method "p" of its single parameter "A* obj", which is a pointer to "A" objects. Now, after creating an object "b" of the class "B" and passing its pointer to "f", "A" gets referenced instead of "B", even if "b" is a "B" object.

#include <iostream>

class A {
public:
    void p() {
        std::cout << "boring...";
    }
};

class B : public A {
public:
    void p() {
        std::cout << "woo!";
    }
};

void f(A * obj) {
    obj->p();
}

int main(int argc, char **argv) {
    B b;
    f(&b);
    return 0;
}

Output:

boring...

Why does this happen?

  • 4
    well to get it to work first, you need to be using something called an Virtual Function. The reason for this is that since A is the Superclass, any subclass will contain all of A's of methods, to function overload or use the name p for both methods you must declare the virtual void in the super class as whatever the default behavior is, and then you can define the functions in subclasses as normal. [Further Explanation here](https://www.geeksforgeeks.org/virtual-function-cpp/) – RyanN1220 Jan 02 '19 at 14:10
  • 1
    Because C++ is not Java. This is how it works in Java, but not C++. – Sam Varshavchik Jan 02 '19 at 14:58

3 Answers3

1

In order to invoke dynamic dispatch (that is, to call the function of the run-time-type), you must mark a function as virtual:

class A {
public:
    virtual void p() {
        std::cout << "boring...";
    }
};

This is because of C++'s philosophy of: you don't pay for what you don't need. And dynamic dispatch is not free, as you need to look up the correct function pointer from the object.

bitmask
  • 32,434
  • 14
  • 99
  • 159
1

One of the fundamental design rules for the C++ language is "you don't pay for what you don't use". Calling functions that are defined in a derived class through a pointer to the base type is a bit tricky, so the rule is that you have to tell the compiler that you mean to do that. So in the code in the question, A* obj = whatever; a->p(); calls A::p (that is, the version of p that's defined in the class A). And B* obj = whatever; b->p(); calls B::p. In order for a->p() to call the version in B you have to tell the compiler that that's what you want to do, and you do that by marking A::p as virtual:

class A {
public:
    virtual void p() {
    }
};
Pete Becker
  • 74,985
  • 8
  • 76
  • 165
0

Virtual dispatch is not automatic in C++. Your object may be a B as well as an A, but f() only knows that you gave it a pointer to an A. It does not know that a B part exists too.

You can get this behaviour using the keyword virtual, with some runtime performance cost.

Consult the chapter in your C++ book about polymorphism for more information.

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055