繁体   English   中英

虚拟功能的动态绑定

[英]Dynamic binding for virtual functions

class base {
public:
    virtual void foo()
    {
         cout << "Base class virutal function " << endl;
     }
}

class Derived : public base {
public:
    void foo()
     {
          cout << "Derived class virtual function " << endl;


int main()
{
    Base b, *ptr;
    Derived d;

    ptr = &b;
    ptr->foo();
    ptr = &d;
    ptr->foo();
}

嗨,我对这里的动态绑定有疑问。 由于编译器知道b.foo()存在时,可以使用基本虚拟函数。 当存在d.foo()时,它可以使用foo的派生版本。 我的意思是编译器在编译时掌握了所有信息,但是仍然有文献说,将使用哪个函数是在运行时确定的。

在这种特定情况1中 ,编译器(至少在理论上)可以确定每种情况下调用哪个函数,并生成代码以直接直接调用这两个函数(并且在我测试了该代码后,大多数编译器都会像这样优化代码)完全一样)。

多态的一个更典型的情况是会涉及某种用户输入,因此不能静态确定要调用的函数。 例如,使用Base类和Derived类,请考虑以下内容:

int main(int argc, char **argv) {
    Base b;
    Derived d;

    Base *arr[] = {&b, &d};

    int i = atoi(argv[1]) != 0;
    arr[i]->foo();
    return 0;
}

在这种情况下,编译器无法确定要静态调用的正确函数-根据运行时在命令行上传递的内容,编译器可能使用foo()的Base或Derived版本。

您似乎也有一种中间情况,您开始尝试将其包括在代码中,但从未真正完成过-您初始化ptr指向您的Base对象,然后指向Derived对象,但是您从未通过ptr调用函数,只能直接放在对象本身上。 如果确实通过指针调用了函数,则与仅直接使用具体对象一起进行操作时,优化起来会更加困难 在这种情况下,较少的编译器将静态确定类型,但是至少有些仍然可以/将要。

1 好吧,无论如何几乎都是这种情况。 就目前而言,该代码将无法编译,因为您已定义了一个名为base的类(小写字母“ b”)并试图实例化一个名为Base的类(大写字母“ B”)。 另外,您的“派生”类实际上并不是从Base派生的,就像您想像的那样。 一旦解决了...

在这里给出的特定示例中,您是正确的; 编译器有足够的信息来知道在编译时要调用哪个函数。 因此,编译器不必在运行时查找函数,但这是一种编译器优化,不会影响程序的结果-编译器可以自由绕过查找或不绕过查找。

您是说编译器可以注意到您将d Base *ptrBase *ptr并在运行时解析了实际的函数地址吗?

如果是,样本在哪里:

if (rand() > 0.5)
{
    ptr = &b;
}
else
{
    ptr = &d;
}

ptr->foo();

编译器如何在运行时知道地址? 这就是为什么存在动态绑定的原因。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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