多态的底层实现逻辑编译器找对应虚函数的步骤this指针-vptr指针-vtable表虚函数表-对应的虚函数通过指针偏移vptr就是虚函数表的起始指针函数指针在虚函数表占的位置也是固定的。其实之前一直没明白为什么重定义不能实现多态这两个例子就可以很好区分重定义代码语言javascriptAI代码解释#define _CRT_SECURE_NO_WARNINGS 1 #include iostream using namespace std; class Animal { public: void speak() { std::cout Animal speaks std::endl; } }; class Dog : public Animal { public: void speak(){ std::cout Dog barks std::endl; } }; class Cat : public Animal { public: void speak() { std::cout Cat meows std::endl; } }; int main() { Animal* a1 new Dog(); Animal* a2 new Cat(); a1-speak(); a2-speak(); delete a1; delete a2; }在上面这个例子中a1a2都是Animal类型他们在不同的作用域中所以不会造成冲突。在调用speak函数的时候直接去基类作用域Animal中寻找都是找到的是基类的speak函数。这和编译器寻找虚函数完全不同重写/覆盖在Dog和Cat类中都有一张虚函数表他们继承父类Anima的虚函数表因为在Cat和Dog中对soeak函数都进行了重写所以他们自己的虚函数表的指针就发生了变化在虚函数表中对父类的speak函数进行覆盖。这样在调用对应的虚函数的时候就可以分别调用不同的虚函数了。调用的过程也是上面这样his指针-vptr指针-vtable表虚函数表-对应的虚函数为什么只有非静态成员函数才可以是虚拟的一个非静态成员函数函数在前面加上virtual就变成了虚函数。因为虚函数是在虚函数表中的虚函数表要靠vptr才能找到vptr要这个对象的this指针才能找到。静态成员函数是不需要靠虚函数的分类有纯虚函数和普通虚函数。有纯虚函数的类不能进行实例化必须在子类重写以后才能实例化。1.什么情况下会有虚函数表当一个类有虚函数的时候就会有虚函数表。2.实例化出来的对象是怎么去调用虚函数的对象会有一个指向虚函数表的虚指针vptr这个指针在64位平台是8字节在32位平台是4字节vptr是虚函数表的起始指针通过指针的偏移就可以找到对应的虚函数地址然后就可以进行函数调用。函数重载重定义重写/覆盖函数重载静态多态在同一个作用域类函数名相同参数不同的函数构成函数重载。仅仅是返回值不同不能构成函数重载。问题为什么编译器可以根据参数的不同构造出不同的函数从而形成函数重载但是仅仅返回值不同不能构成函数重载为了定位一个具体的函数编程语言中引入了函数签名。函数签名1.函数名称。2.参数列表参数的个数类型顺序不同都可以视作为参数列表的不同。在C语言中函数签名没有包含返回值但是有的编程语言中把返回值也作为函数签名的一部分所以如果一个函数的名称相同参数列表相同。只有返回值不同他们的函数签名是一样的。编译器就不能区分他们了。所以函数名相同参数的顺序和个数和类型不同可以区分出不同的函数这些函数叫函数虫子啊。