虚函数的重写所以虚函数的重写实际上在重写的是函数体多态的实现也是靠重写虚函数实现的。注意上边的ptr始终是Person类型的指针图片里说的ptr的指向是指的其指向的对象因为传给ptr的是指向Student的指针ptr指向的对象是Student指向哪个对象调用的就是该对象里的函数体。一道恶心的题问程序运行结果是什么class A { public: virtual void func(int val 1) { std::cout A- val std::endl; } virtual void test() { func(); } }; class B : public A { public: void func(int val 0) { std::cout B- val std::endl; } }; int main(int argc, char* argv[]) { B* p new B; p-test(); p-func(); return 0; }首先明确继承不是拷贝说白了只是改变了编译器的查找逻辑让编译器多到一个地方去找然后定义派生类的对象的时候在内存里上边先有一份基类下边才是自己的成员。p是指向B的指针p调用test函数是先在B里没找到再去A里找到了因此就调用A里的testA里的test的this指针指向的自然就是A*this指针去调用func由于this真正指向的是B因此就去调用B里的func跟上边同理仅仅只是使用函数体函数声明还是A里的函数声明因此val的缺省值是1。所以程序运行结果就是B-1。注意上边的分析都是建立在多态的前提之下的func构成多态满足多态的2个条件。这里别看两个func的参数缺省值不一样但它们是构成重写的重写有3同只要是返回值类型函数名函数参数列表相同(参数列表的类型相同)跟缺省值什么的都没关系。改编此时运行结果又如何。B* p new B; p-func();结果是B-0这里的调用就是普通调用根本不构成多态调用func的仅仅是B*类型的指针也就是派生类自己本类型的指针在调用自己类里边的成员函数。析构函数的重写class A { public: ~A() { cout ~A() endl; } }; class B : public A { public: ~B() { cout ~B() endl; } }; int main() { //普通调用就是直接看类型就可以了 A* p1 new A; A* p2 new B; delete p1; delete p2; return 0; }由于普通调用直接看类型p1和p2都是A类型的指针delete的时候自然就是调用了两次A类里的析构函数没有调用B类的析构此时造成内存泄露。delete的原理是先调用对应类的析构函数再调用operator delete底层用free释放资源。所以我们需要将~A()变成虚函数实现多态解决内存泄露。虚函数表(本质是函数指针数组)当派生类继承含有虚函数的基类时其虚函数表并非直接拷贝基类虚函数表而是以基类虚函数表为模板进行构建编译器先将基类虚函数表的所有条目完整继承到派生类虚函数表中若派生类重写了基类的某个虚函数会将派生类虚函数表中该虚函数对应位置的函数指针替换为派生类自身重写后的函数地址(即实现 “覆盖”)。派生类独有的、基类中没有声明的虚函数会按声明顺序追加到派生类虚函数表的末尾。