C++编译与运行:其一、静态类型和动态类型
一、什么是静态类型和动态类型?
先说结论:编译期间可以明确的类型是静态类型;运行期间才能明确的类型是动态类型。
后半句可能有点不好理解,通俗地说,需要通过执行代码才能明确的类型是动态类型。
假如我们有两个类,分别是基类A,和派生类B。
A a; //静态类型
A * p = new B; //动态类型
第一行,编译的时候编译器就知道了,a的类型是A,所以是静态绑定。
第二行,难道编译的时候,编译器不知道p指向的是B类型的对象吗?抱歉,真的不知道。因为编译过程中,不会执行代码。根据前文的讲解,new B这个过程其实执行了多个函数,所以不会发生在编译过程中,p也就不知道自己到底指向的是什么类型。只有在运行过程中,才知道指向的对象类型是B。当然编译器会提前做一些校验,假如A和B不存在继承关系,那么编译自然会报错。
规范化的说法:
静态类型:对象在声明时采用的类型,在编译期既已确定;
动态类型:通常是指一个指针或引用目前所指对象的类型,是在运行期决定的。
二、什么是静态绑定和动态绑定?
什么是绑定?
把一个方法与类对象关联起来的方法叫绑定。
C++ 程序在运行前需要经过编译阶段,编译时编译器会为代码中的各种变量(static、全局变量等)及代码块(函数)分配存储空间,同时把函数翻译成机器能识别的二进制机器码及完成一些函数跳转动作等。在有虚函数的类中,编译器会给每个类分配一块虚函数表,虚函数表里存放的是虚函数地址。程序运行时,实例化类对象时,对象内存的第一块区域(8 字节)存放了一个虚表指针,该指针指向了该类所拥有的虚函数表。
静态绑定,又叫前期绑定,指在程序运行前就已经知道方法是属于哪个类的,在编译期间就可以链接到类中,定位到这个方法。静态绑定发生于编译器,因此不能利用任何运行期的信息。
动态绑定是指在程序运行过程中,根据具体的实例对象才能具体确定是调用了哪个方法。也就是说,动态绑定只能用到运行期的可用信息。
转自知乎:C++静态绑定和动态绑定
在网上的绝大多数教程中,基本都是用指针+虚函数解释动态绑定。其实指针不是必须的,我们在后面的博客中可以看到具体例子。