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
}