Virtual function declared in a derived class

旧街凉风 提交于 2019-12-23 01:14:27

问题


Here I have declared another virtual function in Derived class.

#include <iostream>

using namespace std;

class A{
    string s;
    public:
    A(const string& name) : s(name){}
     virtual void f1(){cout << "f1 of base class" << endl;};
};

class B : public A{
    string p;
    public:
    B(const string& name) : A(name){}
    virtual void f2(){cout << "virtual function of derived class" << endl;}
    void f1(){cout << "f1 of derived class";}
};

int main() {
    A* arr[] = {new A("John"),new B("Bob")};
    arr[0]->f1();
    arr[1]->f1();
    arr[1]->f2();
    return 0;
}

The function call arr[1]->f2() gives the error "‘class A’ has no member named ‘f2’".I am wondering why the _vptr points to the VTABLE of base class even when B is upcasted to A.

Also I wanted to know , is inlining virtual functions safe?


回答1:


Because there is no such member. virtual functions take place from the class where they are declared first down through all derived classes. They do not get bubbled up. When the compiler looks at arr[ i ]->f2() it looks up the definition of arr for its type. arr has (static) type A. So, the compiler looks up A's definition for a suitable definition of f2 and doesn't find any. Hence the diagnostic.

virtual functions can be safely inlined. In fact, all in-class definitions are implicitly inlined by the compiler. So, your A::f1 is already inlined.




回答2:


You're trying to call f2() on an A*, and A doesn't have f2() declared.

virtual means that the method, when called through a pointer to a base class (including the class of the object itself), is resolved at runtime, based on the vptr table of the object you're calling it on. It doesn't make the method visible in base classes.

Inlining virtual functions is very safe but you won't necessarily get the performance boost you're expecting from it. Inlining means that the function code is copy-pasted by the compiler at the point of call. See The C++ Super-FAQ on inlining and why it's a pie in the sky

Inlining is a compile time concept. Virtual method calls, called on a pointer to a base class, are resolved at runtime.

I.e. the following call to a function that's virtual, can be inlined:

B myB("The B.");
b.f1(); // not virtual, might be inlined



回答3:


Easy first:

Also I wanted to know , is inlining virtual functions safe?

Yes, virtual functions can be inlined, but polymorphism is guaranteed to always work.

For example:

B b;
b.f2();

can be resolved at compile time, without using the virtual table, because the compiler knows the object is of type B.

I am wondering why the _vptr points to the VTABLE of base class even when arr[1] is upcasted to B.

It doesn't. It points to the virtual table of class B, but the compiler doesn't see it. The virtual table is an implementation detail. You're calling a function on an A*, so B's methods aren't visible. In this simple example, it's easy, but how could, in general, the compiler tell that arr[1] is a pointer to a B in fact? That's the whole point of polymorphism, you abstract away the derived type.

What you can do is:

dynamic_cast<B*>(arr[1]) ? (dynamic_cast<B*>(arr[1]))->f2() : (void)0;



回答4:


Think about it this way. At compile time, the compile is completely oblivious of the actual type of the object that arr[i] is pointing to. That type only becomes known at runtime. So when you write something like this:

arr[i]->f2();

the compiler doesn't know what code to produce to make that call happen. What is f2? Is it the f2 that is declared in B? What if you also have a a subclass of A called C, which also has a virtual function named f2, and the object that arr[i] points to just happens to be of type C? We don't know.

You will immediately see that the only sane behavior in such case is to produce an error.




回答5:


arr[1] is of type A* which doesn't have a method called f2. You'd have to cast arr[1] to B*, but I don't think that's a good idea. Change your data structures instead.



来源:https://stackoverflow.com/questions/11113983/virtual-function-declared-in-a-derived-class

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!