如何在运行时决定是否调用派生类函数或基类函数?

时间:2012-04-03 03:01:17

标签: c++

如何在内部(在运行时)决定调用哪个函数,基类或派生类函数。在下面的示例代码中,如何决定调用 B fn() A fn2()

Class A { 
    virtual void fn() { std::cout << "A" < <std::endl; }
    virtual void fn2() { std::cout << "A-fn2" < <std::endl; }
    };

Class B : A
{
    void fn() { std::cout << "B" < <std::endl; }
}

int main() {
    B b = new B;
    A *a = &b;
    a->fn();
    a->fn2();
}

输出 B A-fn2()

基本上如何在运行时决定是调用派生类函数还是基类函数?

2 个答案:

答案 0 :(得分:1)

在纠正编译错误后,您的问题的答案是输出将是:
A A-fn2

您的代码中不存在virtual函数,需要进行任何运行时决策。编译器本身将评估函数的调用。

假设您创建A方法virtual,那么在运行时进行的函数调用决策是基于引用哪个对象

答案 1 :(得分:1)

您所拥有的被称为动态/运行时多态 规则是:
在运行时调用要在运行时调用的方法,具体取决于指针指向的实际对象。
编译器如何执行此操作完全取决于实现。通常,您的代码应该只依赖于行为而不是内部因素。但是,所有已知的编译器都通过虚拟表(vtbl)&amp;虚拟指针(vptr)机制。

如何实现运行时多态?

一个类有一个virtual方法,该类被称为多态类,编译器为该类创建vtblvtbl存储该类中所有虚拟方法的地址。编译器还为该类的每个对象添加一个特殊指针vptrvptr点(存储地址)vtbl 一旦类派生自这样的多态类,编译器将派生类的vtbl中的方法的地址替换为派生类中的覆盖函数的地址。对于非覆盖方法,地址仍然是基类方法。

因此,每个类通常有一个vtbl,而每个对象实例都有一个vptr,它指向vtbl。每个类的vtbl存储其自己的虚拟方法的地址。

在运行时,vptr指针内的this被取出,并进一步获取vtbl中的相应方法地址&amp;然后它被调用,这种机制称为动态调度 因此,由于该机制,可以根据指针所指向的对象的类型来确定要调用的适当方法。

这个C ++ - Faq是一个很好的进一步阅读:
Inheritance — virtual functions