所有带virtual的类的对象,里面最上面有一个隐藏的指针vptr,指向一张表vtable
1 #include <iostream> 2 using namespace std; 3 4 class A 5 { 6 public: 7 A() :i(10) {} 8 virtual void f() { std::cout << "A::f()" << std::endl; } 9 int i; 10 }; 11 12 void main() 13 { 14 A a, b; 15 a.f(); 16 17 std::cout << sizeof(a) << std::endl;//8,不是4 18 19 int *p = (int *)&a; 20 int *q = (int *)&b; 21 22 int *x = (int *)*p; 23 24 std::cout << *x << std::endl; 25 26 std::cout << *p << " " << *q << std::endl;//一样 27 28 system("pause"); 29 }
产生运行时的多态性有如下3个前提:
(1)类之间的继承关系满足赋值兼容性规则
(2)改写了同名虚函数
(3)根据赋值兼容性规则使用指针(或引用)
1 #include <iostream> 2 using namespace std; 3 4 class A 5 { 6 public: 7 A() :i(10) {} 8 virtual void f() { std::cout << "A::f()" << i << std::endl; } 9 int i; 10 }; 11 12 class B :public A 13 { 14 public: 15 B() :j(20) {} 16 virtual void f() { std::cout << "B::f()" << j << std::endl; } 17 int j; 18 }; 19 20 void main() 21 { 22 A a; 23 B b; 24 25 A *p = &a; 26 27 int *r = (int *)&a; 28 int *t = (int *)&b; 29 30 *r = *t; 31 32 p->f(); 33 34 //B *q = &a; 35 //error C2440: “初始化”: 无法从“A *”转换为“B *” 36 //note: 从基类型到派生类型的强制转换需要 dynamic_cast 或 static_cast 37 38 a = b; 39 40 a.f();//A::f()10,必须使用指针或者引用,这样才可以实现多态性 41 42 system("pause"); 43 }
只有基类的析构函数被说明为虚函数,则派生类的析构函数,无论是否使用virtual进行说明,都自动地成为虚函数
如果一个类中定义了虚函数,析构函数也应说明为虚函数,尤其是在析构函数要完成一些有意义的任务时,例如释放内存等