动态类型和静态类型以及多态

发布时间 2023-08-28 10:14:07作者: 小凉拖
  • 一个对象的静态类型在编译的时候就确定了。
  • 一个对象的动态类型是指它指向的对象或则它绑定的对象(因此只有指针和引用才有动态类型),一个对象的动态类型只有编译的时候才会确定。
1 Quote* p = new b_Quote;  // Quote 是基类,b_Quote 是子类

指针 p 的静态类型是 Quote,在编译时已经确定了,但它的动态类型是 b_Quote,运行时才知道

 1 class Base {
 2 public:
 3     Base() {
 4 
 5     }
 6     virtual void fun() {
 7         cout << "Base function" << endl;
 8     }
 9     void func() {
10         cout << "normal function" << endl;
11     }
12 };
13 class Son :public Base {
14 public:
15     Son() {
16 
17     }
18     void fun() {
19         cout << "Son function" << endl;
20     }
21     void func() {
22         cout << "Son's normal function" << endl;
23     }
24 };
25 
26 int main() {
27     Base* base = new Son;
28     base->fun();
29     Base* base1 = new Son;
30     base1->func();
31 }

编译时编译器会首先确定base的静态类型,然后在静态类型中查找是否有fun()函数,如果没有这个函数则编译器会报错。如果找到了就检查base是否是指针或则引用,fun()是否是虚函数。如果上述条件有一项不满足则该函数的类型就是静态类型,此时确定fun()是静态类型的函数;如果上述都满足那么等到运行时判断它的动态类型,运行时判断它的动态类型后通过动态类型的虚函数指针(在类的前4个字节中,虚函数是属于类的而不是哪个对象的)去找到其所指向的虚函数表,然后在虚函数表中找到该虚函数的地址,并进行调用(虚函数表是一个一维数组,查找虚函数表的时间复杂度是O(1))

 

fun()是虚函数,base2也是指针,因此需要在运行时才能确定fun()是属于哪个类型的,结果在运行时发现是一个空指针,空指针调用函数会引发异常。func()不是虚函数,编译时确定它是静态类型的函数,因此调用静态类型的函数不会报错。