首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >对于虚函数,在声明为虚函数和非虚函数时,访问某些方法时会发生什么

对于虚函数,在声明为虚函数和非虚函数时,访问某些方法时会发生什么
EN

Stack Overflow用户
提问于 2011-10-28 05:27:51
回答 2查看 271关注 0票数 0

对于虚函数,当访问某些方法时,当声明为虚时会发生什么,以及当不是时会发生什么。

我的想法是:

如果它是虚拟的,则调用实例将在其虚拟函数表中搜索函数,如果它是指向派生实例的基本实例指针,则将调用派生实例的虚拟函数实现。如果不是虚函数,则调用调用实例的函数。

对吧?

EN

回答 2

Stack Overflow用户

发布于 2011-10-28 05:55:52

从语言标准的角度来看,没有什么比您可能已经知道的更多了:如果一个函数是虚拟的,那么在任何基类引用或指针上调用它将导致调用派生最多的实际函数。

就这样。最重要的是行为。

你真正关心的似乎是编译器如何实现这一点。实际上,vtable是实现虚拟分派的最流行的方法。它本质上是一个函数指针列表,为每个具有虚函数的类维护。(请记住,从具有虚函数的类派生会自动使这些函数在派生类中再次成为虚函数。)

但是,编译器实际调用函数的方式各不相同。

  • 如果函数不是虚拟的,则在编译时知道该函数,并将其静态调度到调用它的静态类类型的成员函数。
  • 如果函数是虚拟的,但编译器可以在编译时证明基引用/指针的动态类型,则它可以选择直接调用相应派生类的函数。
  • 如果编译器无法推断动态类型,则通过在v表中查找实际(派生最多的)函数的函数指针,在运行时执行函数调度。

示例:

代码语言:javascript
复制
struct A {
  void foo();
  virtual void bar();
};
struct B : A {
  void foo(); // hides A::foo() -- very bad style
  void bar(); // automatically virtual!!
};

int main() {
  B x;
  A * a1 = &x;  // pointer-to-base;
  A * a2 = get_pointer();

  a1->foo(); // static dispatch to A::foo() (non-virtual function)
  a1->bar(); // dispatch to B::foo(), possibly resolved statically
  a2->bar(); // dynamically dispatched to whatever the most derived class is
}
票数 1
EN

Stack Overflow用户

发布于 2011-10-28 05:34:21

正确的。如果通过基类指针调用virtual函数,则将调用重写。另一方面,如果通过基类指针调用非virtual函数,则将调用基类函数。

当通过引用而不是指针调用时,也是如此。

在处理基类指针时需要注意的一件事是slicing。如果您这样做:

代码语言:javascript
复制
Base* pb = new Der;
Base other = *pb;

other已经对对象进行了切片,并且所有的Der-ness都消失了。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/7922626

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档