C++ 对于虚拟函数,当访问某些方法时会发生什么情况

C++ 对于虚拟函数,当访问某些方法时会发生什么情况,c++,class,inheritance,object,virtual,C++,Class,Inheritance,Object,Virtual,对于虚拟函数,当访问某些方法时会发生什么情况(声明为虚拟时和声明为非虚拟时) 我的想法是: 如果是虚拟的,调用实例将在其虚拟函数表中搜索函数;如果是指向派生实例的基本实例指针,则将调用派生实例的虚拟函数实现。如果它不是虚拟函数,则调用实例的函数调用将被调用 对吧? 对。如果通过基类指针调用virtual函数,将调用重写。另一方面,如果通过基类指针调用非虚拟函数,则将调用基类函数 当通过引用而不是指针调用时也是如此 处理基类指针时需要注意的一件事是。如果您这样做: Base* pb = new D

对于虚拟函数,当访问某些方法时会发生什么情况(声明为虚拟时和声明为非虚拟时)

我的想法是:

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


对吧?

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

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

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

Base* pb = new Der;
Base other = *pb;

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

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

就这样。重要的是行为

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

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

  • 如果函数不是虚函数,则在编译时已知该函数,并将其静态分派给调用该函数的静态类类型的成员函数

  • 如果函数是虚拟的,但编译器可以在编译时证明基引用/指针的动态类型,那么它可以选择直接调用相应派生类的函数

  • 如果编译器无法推断动态类型,则在运行时通过在vtable中查找实际(最派生)函数的函数指针来进行函数分派

例如:

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
}