本例中为什么需要后期绑定?[重复]

问题描述 投票:0回答:2

我理解为什么在动态创建子类的对象时需要用虚拟关键字来覆盖,但是,在下面的例子中,为什么需要后期绑定(虚拟关键字)来覆盖?编译器难道不能在编译时就知道pa指向的是一个派生类吗?

class A { 
    public: int f() { return 'A';}
};

class B : public A {
    public: int f() { return 'B';} 
};

int main() {

    //I understand this case, since pa is pointing to 
    //something created at runtime, virtual keyword is needed
    //to return 66 
    A* pa;
    pa = new B;
    cout << pa->f() << endl; //returns 65 

    //But why in this case where b2 is created during 
    //compile time, compiler doesn't know pa is pointing
    //to a derived class? 
    B b2; 
    pa = &b2; 
    cout << pa->f() << endl; //returns 65
}
c++ oop pointers binding compiler-construction
2个回答
3
投票

这个问题其实并不是围绕着编译器能不能 "知道 "对象的精确类型而展开的 pa 指的是。它围绕着C++的语义。

当你声明一个方法 f,你告诉编译器你想如何调用到 f 要处理的。在这种情况下 A::f 未声明 virtual你是说,如果 pa->f() 被称为和 pa 具有声明的类型为 A*中的定义,你希望编译器使用在 A::f. 当然可以 *pa 是一个类型的对象 A的对象,尽管它也可能是某个派生类型的对象。A.

另一方面,如果你宣布 f 将要 virtual你告诉编译器,你希望它引用当前对象的最派生类型。pa,并使用以下定义 f 从该类型(或其适当的超类型)。

C++的语义需要是确定性的。也就是说,作为程序员,你需要能够预测哪个定义的 f 在任何情况下都会被使用。如果你仔细想想,在一种语言中,如果有一条规则规定 "使用 B::f 如果你碰巧能够弄清楚,那么 pa 指向一个类型为 B但使用 A::f 如果你不确定 pa 指向"。编译器要想弄清楚什么是 pa 指的是什么?如果将来,编译器团队中有人想出了如何做出更准确的判断,你的程序的语义是否应该神奇地改变?你会满意吗?

请注意,在你介绍的两个片段中,其实很有可能是编译器的 可以 指向的对象的类型是什么?pa 是。所以即使 fvirtual一个优化的编译器可以省略在vtable中查找正确方法的代码,而直接调用正确的方法。C++标准中并没有禁止这样的优化,我相信这样的优化是很常见的。所以,如果将来编译器团队中有人想出了更好的确定变量类型的方法,它不会改变你的程序的语义--它仍然会调用相同的方法。但它可能会导致你的程序更快地调用你的方法。这是一个更有可能让未来的你满意的结果。


1
投票

这一切都围绕着C++是一种静态类型的语言这一事实来解决。 因此。pa 被编译器视为指向一个 A的指针,而不是指向一个 B (因为您声明它是这样的),因此,如果您调用了 pa->f() 它将呼叫 A::f() 而非 B::f() 除非 f() 被声明为虚拟方法。

事实上,这就是虚拟方法的全部意义--当你通过多态指针调用方法时,派遣到正确的方法。


0
投票

在你展示的这个简单的例子中,是的,编译器可以轻而易举的发现 pa 是指向一个对象的指针,其动态类型是 B.

但是,为了以你所描述的方式使用这些信息,有几件事必须是真的。

  1. 指针工作的规则必须是: 需要 这些信息,在任何情况下
  2. 这些信息必须在一个简单的例子中才能获得(它不是--通过 pa 到另一个翻译单元中的函数,突然间编译器运行处理该单元时不知道动态类型是什么;一些 例子 在三小时前你提出这个问题时,你已经给出了答案)
  3. 我们作为程序员,一般会 想要 这种行为(我们没有--我们可以选择用 virtual 如果我们喜欢的话,但除此之外,我们想要简单的行为,表达式的类型定义了表达式的含义和操作数的作用)。)

最后,请注意您对动态 自动存储持续时间分配方法作为 "运行时 "与 "编译时 "是不太准确的,不过考虑到构建和运行一个C++程序涉及到许多不同的抽象层,这些术语无论如何都会变得很毛躁。

© www.soinside.com 2019 - 2024. All rights reserved.