class Base
{
public:
virtual func1() {};
virtual func2() {};
}
class Child : public Base
{
public:
virtual func1() {};
virtual func3() {};
}
Base* b = new Child();
b->func1();
要讨论的是 `b->func1()`编译器以及运行时是怎么操作的
先说结论:
1.编译器会给每个虚函数指定一个在虚函数表中的索引
2.在编译期,虚函数的调用以及被类似转化成`(*p->vptr[1])(p)` 这种形式,前面获取到func1的地址,然后调用,传的参数是p(表示this指针)。(假设func1函数是在索引1的位置,实际上从书中得知,虚函数表的第0位置存放的是type_info,虚函数都是从索引1的位置开始)
有人会问,虚函数调用在编译期转换成了`(*p->vptr[1])(p)` 这种形式,那岂不是写死了调用的是哪一个函数?但是在运行期才知道是调用的是基类还是子类的函数啊?
这个问题其实是不存在的, `(*p->vptr[1])(p)` 这样只是在运行时告诉CPU,要去虚函数表索引为1的地方读取函数地址,这个函数的地址却不是编译期能确定的,因为可以b指针可以指向父类也可以指向子类。所以在运行时,