简体   繁体   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();
}

Hi, I have a doubt regarding dymnamic binding here. 嗨,我对这里的动态绑定有疑问。 since compiler knows that when b.foo() is there it can use base virtual fumction. 由于编译器知道b.foo()存在时,可以使用基本虚拟函数。 and when d.foo() is present it can use derived version of foo. 当存在d.foo()时,它可以使用foo的派生版本。 I mean compiler has every bit of info during compile time but still literature says that which function will be used is decided at run time. 我的意思是编译器在编译时掌握了所有信息,但是仍然有文献说,将使用哪个函数是在运行时确定的。

In this specific case 1 , the compiler (at least in theory) can determine which function is called in each case, and generate code to simply call the two functions directly (and when I've tested it, most compilers will optimize code like this exactly that way). 在这种特定情况1中 ,编译器(至少在理论上)可以确定每种情况下调用哪个函数,并生成代码以直接直接调用这两个函数(并且在我测试了该代码后,大多数编译器都会像这样优化代码)完全一样)。

A more typical case for polymorphism would involve some sort of user input, so the function to be called can't be determined statically. 多态的一个更典型的情况是会涉及某种用户输入,因此不能静态确定要调用的函数。 For example, using your Base and Derived classes, consider something like: 例如,使用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;
}

In this case, the compiler can't determine the correct function to call statically -- depending on what you pass on the command line when you run it, it might use either the Base or the Derived version of foo() . 在这种情况下,编译器无法确定要静态调用的正确函数-根据运行时在命令行上传递的内容,编译器可能使用foo()的Base或Derived版本。

You also seem to have a kind-of intermediate case you started to try to include in your code, but never really completed -- you initialize ptr to point at your Base object and then your Derived object, but you never invoke a function via ptr , only directly on the objects themselves. 您似乎也有一种中间情况,您开始尝试将其包括在代码中,但从未真正完成过-您初始化ptr指向您的Base对象,然后指向Derived对象,但是您从未通过ptr调用函数,只能直接放在对象本身上。 If you did invoke the functions via the pointer, it would be harder to optimize than when working only directly with concrete objects. 如果确实通过指针调用了函数,则与仅直接使用具体对象一起进行操作时,优化起来会更加困难 Fewer compilers will determine the type statically in this case, but at least some still can/will. 在这种情况下,较少的编译器将静态确定类型,但是至少有些仍然可以/将要。

1 Well, almost this specific case anyway. 1 好吧,无论如何几乎都是这种情况。 As it stands right now, the code won't compile, because you've defined a class named base (lower-case 'b') and tried to instantiate a class named Base (upper-case 'B'). 就目前而言,该代码将无法编译,因为您已定义了一个名为base的类(小写字母“ b”)并试图实例化一个名为Base的类(大写字母“ B”)。 Also, your "Derived" class isn't actually derived from Base , as you presumably intended. 另外,您的“派生”类实际上并不是从Base派生的,就像您想像的那样。 Once those are fixed though... 一旦解决了...

In the specific example you give here, you're correct; 在这里给出的特定示例中,您是正确的; the compiler has enough information to know which function to call at compile time. 编译器有足够的信息来知道在编译时要调用哪个函数。 The compiler thus does not have to look up the function at run time, but this is a compiler optimization that does not affect the result of the program - the compiler is free to bypass the lookup or not. 因此,编译器不必在运行时查找函数,但这是一种编译器优化,不会影响程序的结果-编译器可以自由绕过查找或不绕过查找。

Are you saying that compiler can notice that you cast d to Base *ptr and resolve actual function address at runtime? 您是说编译器可以注意到您将d Base *ptrBase *ptr并在运行时解析了实际的函数地址吗?

If yes, where is a sample: 如果是,样本在哪里:

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

ptr->foo();

how can compiler know address at runtime? 编译器如何在运行时知道地址? That's why dynamic binding is there. 这就是为什么存在动态绑定的原因。

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

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