【转】C++动态绑定,静态绑定,虚函数
2017-11-07 14:17
375 查看
动态类型
是指由一个左值表达式表示的左值所引用的最终派生对象的类型。例:如果一个静态类型为“类 B ”的指针p 指向一个继承于 B的类 D 的对象,则表达式 *p 的动态类型为“D”。引用按照相似规则处理。一般地讲,基类的指针和基类引用有可能为动态类型,就是说在运行之前不能够确定其真实类型。通常我们说,“基类指针指向的对象的实际/真正类型”或“基类引用所引用的对象的实际/真正类型”,就是它们的动态类型。很显然,这个动态类型是 C++ 语言通过指针和引用实现运行时多态能力的核心概念。
静态绑定:编译时绑定,通过对象调用
动态绑定:运行时绑定,通过地址实现
只有采用“指针->函数()”或“引用变量.函数()”的方式调用C++类中的虚函数才会执行动态绑定。对于C++中的非虚函数,因为其不具备动态绑定的特征,所以不管采用什么样的方式调用,都不会执行动态绑定。
即所谓动态绑定,就是基类的指针或引用有可能指向不同的派生类对象,对于非虚函数,执行时实际调用该函数的对象类型即为该指针或引用的静态类型(基类类型);而对于虚函数,执行时实际调用该函数的对象类型为该指针或引用所指对象的实际类型。
虚函数是动态绑定的基础;动态绑定是实现运行时多态的基础。
要触发动态绑定,需满足两个条件:
(1) 只有虚函数才能进行动态绑定,非虚函数不进行动态绑定。
(2) 必须通过基类类型的引用或指针进行函数调用。
通过基类指针或基类引用做形参,当实参传入不同的派生类(或基类)的指针或引用,在函数内部触发动态绑定,从而来运行时实现多态的。
只有具有virtual函数的多态基类(或者其它想当base class的类)才应该将析构函数设置为virtual,对于普通的类则无必要。因为虚函数的实现要求对象携带额外信息,也就是维护一个指向虚函数表的指针vptr(virtual table pointer),vptr指向虚函数表vtbl(virtual table)。当调用一个对象的虚函数时,就会通过vptr找到vtbl,在vtbl中寻找正确的函数指针调用。由于vptr的加入,导致对象大小增加。
另外,有时还会将析构函数设置为纯虚函数(pure virtual),拥有纯虚函数的类变为抽象基类(abstract class),抽象基类不能被实例化。如果某个class只希望作为base class(不希望被实例化),但是又没有一个纯虚函数,而base class应该有一个virtual析构函数,那么此时就可以将析构函数设置为纯虚函数。
必须为纯虚析构函数提供定义,否则会出现Link错误。因为析构函数的运作方式是,最深层派生(most derived)的那个class其析构函数最先被调用。然后是其每一个base class的析构函数被调用。
是指由一个左值表达式表示的左值所引用的最终派生对象的类型。例:如果一个静态类型为“类 B ”的指针p 指向一个继承于 B的类 D 的对象,则表达式 *p 的动态类型为“D”。引用按照相似规则处理。一般地讲,基类的指针和基类引用有可能为动态类型,就是说在运行之前不能够确定其真实类型。通常我们说,“基类指针指向的对象的实际/真正类型”或“基类引用所引用的对象的实际/真正类型”,就是它们的动态类型。很显然,这个动态类型是 C++ 语言通过指针和引用实现运行时多态能力的核心概念。
静态绑定:编译时绑定,通过对象调用
动态绑定:运行时绑定,通过地址实现
只有采用“指针->函数()”或“引用变量.函数()”的方式调用C++类中的虚函数才会执行动态绑定。对于C++中的非虚函数,因为其不具备动态绑定的特征,所以不管采用什么样的方式调用,都不会执行动态绑定。
即所谓动态绑定,就是基类的指针或引用有可能指向不同的派生类对象,对于非虚函数,执行时实际调用该函数的对象类型即为该指针或引用的静态类型(基类类型);而对于虚函数,执行时实际调用该函数的对象类型为该指针或引用所指对象的实际类型。
虚函数是动态绑定的基础;动态绑定是实现运行时多态的基础。
要触发动态绑定,需满足两个条件:
(1) 只有虚函数才能进行动态绑定,非虚函数不进行动态绑定。
(2) 必须通过基类类型的引用或指针进行函数调用。
通过基类指针或基类引用做形参,当实参传入不同的派生类(或基类)的指针或引用,在函数内部触发动态绑定,从而来运行时实现多态的。
只有具有virtual函数的多态基类(或者其它想当base class的类)才应该将析构函数设置为virtual,对于普通的类则无必要。因为虚函数的实现要求对象携带额外信息,也就是维护一个指向虚函数表的指针vptr(virtual table pointer),vptr指向虚函数表vtbl(virtual table)。当调用一个对象的虚函数时,就会通过vptr找到vtbl,在vtbl中寻找正确的函数指针调用。由于vptr的加入,导致对象大小增加。
另外,有时还会将析构函数设置为纯虚函数(pure virtual),拥有纯虚函数的类变为抽象基类(abstract class),抽象基类不能被实例化。如果某个class只希望作为base class(不希望被实例化),但是又没有一个纯虚函数,而base class应该有一个virtual析构函数,那么此时就可以将析构函数设置为纯虚函数。
必须为纯虚析构函数提供定义,否则会出现Link错误。因为析构函数的运作方式是,最深层派生(most derived)的那个class其析构函数最先被调用。然后是其每一个base class的析构函数被调用。
相关文章推荐
- 深入理解C++的动态绑定和静态绑定
- 深入理解C++的动态绑定和静态绑定
- c++动态绑定与静态绑定
- C++中的动态类型与动态绑定、虚函数、运行时多态的实现
- 深入理解C++的动态绑定和静态绑定
- 面试题 C++ 动态绑定 虚函数
- c++动态绑定、静态绑定与java中动态绑定与静态绑定的比较
- C++ 静态绑定和动态绑定
- C++ — 静态绑定与动态绑定
- 虚函数,静态与动态绑定
- C++ 虚函数的深入思考 -动态绑定案例
- 深入理解C++的动态绑定和静态绑定
- 关于静态绑定与动态绑定的辨别笔记----C++学习之路
- 深入理解C++的动态绑定和静态绑定
- C++动态绑定与静态绑定
- 深入理解C++的动态绑定与静态绑定的应用详解
- c++静态绑定和动态绑定以及虚函数中缺省参数的绑定
- 深入理解C++的动态绑定和静态绑定
- C++中的动态类型与动态绑定、虚函数、运行时多态的实现
- c++的动态绑定和静态绑定