动态绑定与继承:不得不去想细节
来源:互联网 发布:域名设置教程 编辑:程序博客网 时间:2024/06/05 20:11
C++动态绑定,也就是在一个点上会发生~~~~~~~~~~~
这个点就是:
p->f();
看上面的函数:
当p去寻找f()的时候,
发现f()是虚函数,
这个时候:
p开始进行自我反省,它发现了所指向的对象的类型后,调用相关的实现。
把p强制转换为派生类的this,然后传给这个函数!
整个过程p本身没有发生类型转换,只是说:
把自己作为了派生类的指针传给了隐藏的this形参;
总结如下:
1. c++是强类型语言,不去转换类型,它就永远不会自动转换。
2. 转换发生在对函数的参数传递过程中,我们无法控制。
有两个东西可以控制强制类型转换:
typeid
dynamic_cast
这两个东西被称为C++运行时:
对于带虚函数的类来说:
动态绑定发生在运行时期,
而typeid和dynamic_cast;目的是获取对象的实际类型和转换类型,因此也发生在运行时期。
例如:
class A{
f();
}
class B:A{
g();
}
A* pA=new B();
if(B* p=dynamic_cast<B*>(pA))
p.g();
else
throw new dynamic_cast error();
#include <cstdlib>#include <iostream>using namespace std;class A{ };class B:public A{ public : void f(){ cout<<"Hello!"<<endl; } };int main(int argc, char *argv[]){ A *pA; ((B*)pA)->f(); system("PAUSE"); return EXIT_SUCCESS;}
对于上面的代码我想说的是:如果感觉强制转换很无奈!~~~~那么可以把这些强制转换进行封装:
经过测试下面的代码,没有任何输出:
#include <cstdlib>#include <iostream>using namespace std;class A{friend class C; };class B:public A{friend class C; public : void f(){ cout<<"Hello!"<<endl; } };class C{ A* pa; public: C(A* p_a):pa(p_a){ }; void f(){ if(typeid(B).name()==typeid(*pa).name()) ((B*)pa)->f(); else { } } };int main(int argc, char *argv[]){ C c(new B()); c.f(); system("PAUSE"); return EXIT_SUCCESS;}
现在在A里面添加虚函数:
#include <cstdlib>#include <iostream>using namespace std;class A{ enum _NOINITMYA{a,b};private: virtual void myf(_NOINITMYA b1=b){}; friend class C; };class B:public A{friend class C; public : void f(){ cout<<"Hello!"<<endl; } };class C{ A* pa; public: C(A* p_a):pa(p_a){ }; void f(){ if(typeid(B).name()==typeid(*pa).name()) ((B*)pa)->f(); else { } } };int main(int argc, char *argv[]){ C c(new B()); c.f(); system("PAUSE"); return EXIT_SUCCESS;}
从上面可以看到。c.f()有了结果。传递的参数实际类型为A,那么就会有如下结果:
#include <cstdlib>#include <iostream>using namespace std;class A{ enum _NOINITMYA{a,b};private: virtual void myf(_NOINITMYA b1=b){}; friend class C; };class B:public A{friend class C; public : void f(){ cout<<"Hello!"<<endl; } };class C{ A* pa; public: C(A* p_a):pa(p_a){ }; void f(){ if(typeid(B).name()==typeid(*pa).name()) ((B*)pa)->f(); else {
// throw new DYNAMIC_CAST_ERROR(); } } };int main(int argc, char *argv[]){ C c(new B()); c.f(); C c1(new A()); c1.f(); system("PAUSE"); return EXIT_SUCCESS;}
上面的代码中,c1.f()无结果。其实这是一个错误,直接throw一个类型转换的错误。
- 动态绑定与继承:不得不去想细节
- 【C++基础】 继承与动态绑定
- C++ primer 继承与动态绑定
- 【Java学习笔记】继承,动态绑定与静态绑定
- 继承和动态绑定
- 牛刀小试 - 浅析Java的继承与动态绑定
- B 类 对象 继承 多态与动态绑定
- 继承与多态,动态绑定,final,abstract
- C++动态绑定及继承
- 继承 动态绑定 默认参数
- 抽象、继承和动态绑定
- 关于继承,动态绑定,静态绑定
- java中转型(upcasting)与动态绑定(dynamic binding)或者后期(late binding)细节
- java中转型(upcasting)与动态绑定(dynamic binding)或者后期(late binding)细节
- 继承与多态---细节
- 静态绑定与动态绑定
- 动态绑定与静态绑定
- 静态绑定与动态绑定
- 理解Fragment,生命周期以及各个周期做什么事,缓存fragment不被销毁。
- 中国剩余定理
- c++中的变量。
- JDK各版本的下载
- mui.openWindow参数
- 动态绑定与继承:不得不去想细节
- OpenGL双缓冲
- CS231n Spring 2017 Module1 翻译学习
- GameThoery
- 把成员函数转换为函数的代码。
- git命令操作
- CC2640R2F BLE5.0 CC2640R2F SPI驱动实现
- Android在线更新SDK的方法(使用国内镜像)
- Linux下Gcc生成和使用静态库和动态库详解(转)