我想了解以下涉及虚函数的C ++程序输出背后的原因。还请解释如何在以下两种情况下生成包含指向函数指针表的链接的函数指针表和虚拟指针表,以及如何在运行时解析调用。
/******* PROGRAM 1 *******/
#include <iostream>
using namespace std;
class Car {
public:
virtual void foo() {
cout<<"Car"<<endl;
}
};
class Bmw: public Car {
public:
void foo1() {
cout<<"Bmw"<<endl;
}
};
int main() {
Car *c = new Bmw();
c->foo(); // gives output Car even though foo()
//function does not exist in BMS class.
return 0;
}
/******* PROGRAM 2 *******/
#include<iostream>
using namespace std;
class Car {
public:
virtual void foo() {
cout<<"Car"<<endl;
}
};
class Bmw: public Car {
public:
void foo() {
cout<<"Bmw"<<endl;
}
};
class Bmw7: public Bmw {
public:
void foo1(){
cout<<"Bmw7"<<endl;
}
};
int main() {
Car *c = new Bmw7();
c->foo(); //gives output Bmw. Why output is not Car ??
return 0;
}
Here是虚函数和vtable的一个很好的解释。
使用虚函数(或从使用虚函数的类派生)的每个类都有自己的虚拟表
此表中的每个条目只是一个函数指针,指向该类可访问的最派生函数。
这几乎可以回答你的问题。在第一个例子中,c
可以访问的最多派生函数是Car
的foo
。而在第二个是Bmw
的foo
。即使你没有在virtual
的foo
(这不是一个很好的编码风格)前面写Bmw
,它的虚拟性继承自Car
。
编辑:正如评论中正确陈述的那样,vtable不是标准的一部分。有关更正式的解释,请参阅this reference。
对于每个虚函数,都有最终的覆盖,在进行虚函数调用时执行。除非派生类声明或继承(通过多重继承)另一个覆盖vf的函数,否则基类Base的虚拟成员函数vf是最终的覆盖。