[英]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 *ptr
为Base *ptr
并在运行时解析了实际的函数地址吗?
如果是,样本在哪里:
if (rand() > 0.5)
{
ptr = &b;
}
else
{
ptr = &d;
}
ptr->foo();
编译器如何在运行时知道地址? 这就是为什么存在动态绑定的原因。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.