简体   繁体   中英

query on runtime polymorphism in C++

class base
{
public:
    virtual void showbase() {
        // ----------
    }
};

class base1 {
public:
    virtual void showbase1() {
        // -------
    }
};

class derived : public base, public base1
{
    void showbase() {
        // ----  
    }

    void showbase1() {
        // -------
    }
};

int main()
{
    base* p = new derived();
    p->showbase1();

    base1* p1 = new derived();
    p1->showbase();
}

As per my understanding about virtual function is that compiler deals it with run time (vtable mechanism), then why I am getting compile time error.

To simulate a compiler, consider what a compiler sees:

class base
{
public:
    virtual void showbase() {
        // ----------
    }
};

base* p = /*blah blah*/;
p->showbase1();

Yes, base is a polymorphic class. And p is indeed a pointer-to base . But since p points just to a base , and importantly not to a base1 (where showbase1 lives) the compiler interprets the above code like this. Obviously, I'm paraphrasing:

 Here is a class named `base` with a single virtual method called `showbase`. Here is a pointer to a `base` object. Call the method named `showbase1` 

And the compiler complains:

Um, excuse me buddy, but base doesn't have a method called showbase1 .


You asked:

[My] understanding about virtual function is that compiler deals with it at run time. Why I am getting compile time error?

Because the code you've written is nonsense. Here basically is how polymorphism works.

  1. You define a base class with virtual methods.
  2. You define a derived class that overrides those virtual methods.
  3. The compiler creates a vtable which maps the names of the methods in the base class to the implementation in the derived class.
  4. When you call a method in the base class through a pointer (or ref) to the base class, the derived class' implementation is called.

But what you are trying to do is:

  1. Define a base class with virtual methods.
  2. Define a derived class which overrides those virtual methods.
  3. Call a function in a completely different class.

Your base class(es) only know about their own member functions, so you can't use it this way. You could do this instead:

base* p = new derived();
p->showbase();

base1* p1 = new derived();
p1->showbase1();

To answer your question about runtime polymorphism, it is dealing with runtime polymorphism (late binding) via the vtable, as you say. But with multiple inheritance, there is essentially a vtable for for each base class. You can't access one base class' vtable via a pointer to the other base class.

A base class pointer to a derived class can only access the member functions defined in the base class. It is illegal to try and access other functions defined in the derived class through it. In your case base class does not define showbase1 and therefore this is illegal

base* p = new derived();
p->showbase1(); //illegal

However, you can do this:

p->showbase(); // legal because showbase is a member function of base

Similarly you can't access showbase1 using a base class pointer

base1* p1 = new derived();
p1->showbase();  //illegal
p1->showbase1(); //legal

As per my understanding about virtual function is that compiler deals it with run time (vtable mechanism), then why I am getting compile time error.

"Deals with it" is pretty vague and vtables are not magic; In C++ virtual dispatch allows for the actual function called to be one that overrides the statically declared virtual function. That means that the function which is being overridden must be known at compile time.

The vtable does not contain information that would be necessary to look up functions at run-time. Instead, it's basically just a list of pointers to overriding functions. The base provides a complete list of its virtual functions and so, given a particular base type, the compiler knows at compile-time where to go in the vtable for that base for a particular function override; The compiler can generate code that goes directly to that spot in the vtable, gets the pointer, and calls the overriding function.

Then, at run-time, when the actual object of derived type is created, the derived object's constructor fills in the base's vtable, so that anything checking the vtable will get pointers to the derived type's functions.

So the problem with your code is that the function you're calling, showbase() , is not on the list of virtual functions for the type the compiler knows you're accessing, base1 ; The compiler can't know where in base1's vtable to get a pointer for a function override named showbase() , because there is no such entry in base1 's vtable.

p ' static type s type is base and hence you can only call with it functions that have been definied into base even if at the end, it will be the functions from derived which will be called because p's dynamic type is derived

Same thing happens for p1.

Maybe you meant p->showbase(); and p1->showbase1();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM