深入了解虚拟函数的静态类型和动态类型
2009-03-20 09:43
274 查看
先来看一个问题,如果一个子类重载的虚拟函数为privete,那么通过父类的指针可以访问到它吗?
运行时会输出 driver fun called
从这个实验,可以更深入的了解虚拟函数编译时的一些特征:
在编译虚拟函数调用的时候,例如p->fun(); 只是按其静态类型来处理的, 在这里p的类型就是B,不会考虑其实际指向的类型(动态类型)。
也就是说,碰到p->fun();编译器就当作调用B的fun来进行相应的检查和处理。
因为在B里fun是public的,所以这里在“访问控制检查”这一关就完全可以通过了。然后就会转换成(*p->vptr[1])(p)这样的方式处理, p实际指向的动态类型是D,所以p作为参数传给fun后(类的非静态成员函数都会编译加一个指针参数,指向调用该函数的对象,我们平常用的this就是该指针的值), 实际运行时p->vptr[1]则获取到的是D::fun()的地址,也就调用了该函数, 这也就是动态运行的机理。
为了进一步的实验,可以将B里的fun改为private的,D里的改为public的,则编译就会出错。
C++的注意条款中有一条" 绝不重新定义继承而来的缺省参数值" (Effective C++ Item37, never redefine a function's inherited default parameter value) 也是同样的道理。
可以再做个实验
则运行会输出driver fun called, 1
关于这一点,Effective上讲的很清楚“virtual 函数系动态绑定, 而缺省参数却是静态绑定”,也就是说在编译的时候已经按照p的静态类型处理其默认参数了,转换成了(*p->vptr[1])(p, 1)这样的方式。
#include <IOSTREAM> class B { public: virtual void fun() { std::cout << "base fun called"; }; }; class D : public B { private: virtual void fun() { std::cout << "driver fun called"; }; }; int main(int argc, char* argv[]) { B* p = new D(); p->fun(); return 0; }
运行时会输出 driver fun called
从这个实验,可以更深入的了解虚拟函数编译时的一些特征:
在编译虚拟函数调用的时候,例如p->fun(); 只是按其静态类型来处理的, 在这里p的类型就是B,不会考虑其实际指向的类型(动态类型)。
也就是说,碰到p->fun();编译器就当作调用B的fun来进行相应的检查和处理。
因为在B里fun是public的,所以这里在“访问控制检查”这一关就完全可以通过了。然后就会转换成(*p->vptr[1])(p)这样的方式处理, p实际指向的动态类型是D,所以p作为参数传给fun后(类的非静态成员函数都会编译加一个指针参数,指向调用该函数的对象,我们平常用的this就是该指针的值), 实际运行时p->vptr[1]则获取到的是D::fun()的地址,也就调用了该函数, 这也就是动态运行的机理。
为了进一步的实验,可以将B里的fun改为private的,D里的改为public的,则编译就会出错。
C++的注意条款中有一条" 绝不重新定义继承而来的缺省参数值" (Effective C++ Item37, never redefine a function's inherited default parameter value) 也是同样的道理。
可以再做个实验
class B { public: virtual void fun(int i = 1) { std::cout << "base fun called, " << i; }; }; class D : public B { private: virtual void fun(int i = 2) { std::cout << "driver fun called, " << i; }; };
则运行会输出driver fun called, 1
关于这一点,Effective上讲的很清楚“virtual 函数系动态绑定, 而缺省参数却是静态绑定”,也就是说在编译的时候已经按照p的静态类型处理其默认参数了,转换成了(*p->vptr[1])(p, 1)这样的方式。
相关文章推荐
- 解析C++中的虚拟函数及其静态类型和动态类型
- 深入了解网站中的静态网页和动态网页的相关知识
- 动态语言和静态语言、编译型语言和解释型语言、强类型语言和弱类型语言的分析(深入探讨)
- 深入解析C++中的动态类型转换与静态类型转换运算符
- [置顶] 【R语言数据类型】深入了解 向量、矩阵、数据框、列表
- 动态,静态,强类型,弱类型
- 静态类型与动态类型
- 强类型、弱类型、静态、动态语言定义
- 深入理解代理模式:静态代理与JDK动态代理
- 了解流程类型,第 3 篇:动态消息广告
- 静态编程语言、动态编程语言以及静态类型语言和动态类型语言
- 编译型与解释型、动态语言与静态语言、强类型语言与弱类型语言的区别
- Delphi 无类型参数传递动态数组和静态数组
- MYSQL表的类型 静态表 动态表 压缩表
- C++基础--------带默认参数的虚函数 静态类型和动态类型分析
- 强弱类型,动态静态语言比较(JAVA,C,C++,Python,Ruby,PHP,Perl)
- JavaScript 参数 arguments深入了解以及javascript内置数据类型的讨论
- 深入了解c++的动态绑定和静态绑定
- 关于动态语言和静态语言、强类型定义语言和弱类型定义语言的概念区分
- 编译型与解释型、动态语言与静态语言、强类型语言与弱类型语言的区别