继承中的虚拟调用

时间:2011-04-05 01:29:19

标签: c++ inheritance

如何在编译时或从任何类的运行时解析对函数的调用?

例如 - 在下面的“调用show()时从派生类中,是否会在运行时解析?”

#include <iostream>
using std::ostream;

class Base 
{
public:
    virtual void show() {

         show(); //Call derived class 'show()'
    }
};

class Derived : public Base {

public:

    void show() {

         show(); //Call to itself, Would this call be resolved at run-time?
    }
};

ostream& operator <<(ostream &os, Base &obj)
{

    obj.Base::show();
    return os;
}

int main()
{
    Derived D;

    cout << D << endl;
}

3 个答案:

答案 0 :(得分:2)

每当通过具体类型的对象(即没有指针)调用成员函数时,静态类型是已知的,因此编译器在编译时解析正确的函数。 在运行时解析虚函数的唯一时间是使用多态在指向对象的指针上调用它们。

在您的示例中,对show()的调用是通过“this”指针进行的,随后它们将在运行时解析。考虑到实现show()的继承链中可能总是存在一个类。

显式限定的调用“obj.Base :: show()”显然在编译时解析。

答案 1 :(得分:0)

每当编译器可以确定要调用的函数的重载时,它就会。保证能够在

时这样做
  • 它具有完整的对象类型(例如Foo foo; foo.bar();
  • 你告诉它要调用哪个重载(例如Foo foo; foo.Bar::bar();

但是可能能够在不太明显的情况下做到这一点 - 也就是说,如果它可以弄清楚“这个Foo的指针总是指向Bar ”。这称为 devirtualization ,是优化编译器所具有的夜间护目镜的一部分。根据您的编译器,并且根据您的真实代码,可以执行此优化 - 并直接调用您的函数而不通过vtable。

答案 2 :(得分:0)

要回答你的问题,在代码中obj.Base :: show()在编译时被解析,因为显式调用了Base函数。如果要在运行时解决此问题,则可以使用指向Base的指针并向其传递指向Derived的指针。

例如:

ostream& operator <<(ostream &os, Base *obj)
{    
    obj->show();
    return os;
}

int main()
{
    Derived D;    
    cout << &D << endl;
}

我不确定你要做什么。从您的代码中,您似乎希望从基类'show()'函数中调用派生(多态,在运行时版本中解析)。没有必要这样做,因为Derived版本是自动调用的,因为它是虚拟的。