Virtual function calling a non-virtual function

那年仲夏 提交于 2019-12-06 00:18:54

In Bar::foo(), you are calling foo2(). This is really equivalent to calling this->foo2(). The type of this is Bar, so this is really equivalent to:

void Bar::foo()
{
    Bar *bar = this;
    bar->foo2();
}

So there's no polymorphism involved at this point; the call is resolved to Bar::foo2 at compile-time, rather than dynamically at run-time.

because Bars foo is what's calling foo2, at that stage it knows its a Bar....

try again, except call foo2 directly in main for both rather than foo calling foo2

int main()
{
    Foo* f = new Foo;
    f->foo();
    f->foo2();

    Foo* b = new Bar;
    b->foo();
    b->foo2();

    return 0;
}

how is foo2() of the derived class getting called?

You expect Bar::foo2 to never be called. Then your question can be reformulated as: "why is the purpose of Bar::foo2, if any?"

Its purpose is to be called when dealing with Bar objects. The foo2 of a Bar object is called whenever foo2 is called.

It is only for foo objects that it matters whether Foo::bar2 is virtual or not. Inheritance never forces you to use the functions with the same signature in the base class, if you are dealing directly with derived class objects. (It would cause too many unpleasant surprises to have the inheritance rules work differently in this matter.)

What you have essentially done is hiding. By creating a function with the same signature in Bar, you have hidden the nonvirtual function in the base class Foo. This is typically a bad design because it is unnecessarily complex - it is better to choose different names for different things, to avoid hiding. Hiding is seldom part of a conscious good design.

void Bar::foo()
{
    cout << "In BAR - foo 1" << endl;
    foo2();
}

This is because Bar::foo2() is the foo2() called by foo(). Bar::foo2() is local to Bar::foo() and has precedence. It's just static dispatch from Bar::foo2().

If the behavior you expected is what you really want, you can choose the method by specifying its scope like so:

void Bar::foo()
{
    cout << "In BAR - foo 1" << endl;
    Foo::foo2();
}

So this really does not have to do with dynamic dispatch.

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