34 虚函数与多态(一)
2016-03-30 11:26
267 查看
静态绑定与动态绑定
静态绑定绑定过程出现在编译阶段,在编译期就已确定要调用的函数。
动态绑定
绑定过程工作在程序运行时执行,在程序运行时才确定将要调用的函数。
只有通过基类指针或引用调用虚函数才能引发动态绑定
#include <iostream> using namespace std; class Base { public: virtual void Fun1() { cout << "Base::Fun1 ..." << endl; } virtual void Fun2() { cout << "Base::Fun2 ..." << endl; } void Fun3() { cout << "Base::Fun3 ..." << endl; } }; class Derived :public Base { public: /*virtual*/ void Fun1()//如果一个函数在基类中被声明为虚函数,则他在所有派生类中都是虚函数 { cout << "Derived::Fun1 ..." << endl; } /*virtual*/ void Fun2() { cout << "Derived::Fun2 ..." << endl; } void Fun3() { cout << "Derived::Fun3 ..." << endl; } }; int main(void) { Base* p; Derived d; p = &d; p->Fun1(); //Fun1是虚函数,基类指针指向派生类对象,调用的是派生类对象的虚函数 p->Fun2(); p->Fun3(); //Fun3非虚函数,根据p指针实际类型来调用相应类的成员函数 return 0; }
#include <iostream> using namespace std; class Base { public: virtual void Fun1() { cout << "Base::Fun1 ..." << endl; } virtual void Fun2() { cout << "Base::Fun2 ..." << endl; } void Fun3() { cout << "Base::Fun3 ..." << endl; } Base() { cout << "Base ..." << endl; } //如果一个类要做为多态基类,要将析构函数定义成虚函数 virtual ~Base() { cout << "~Base ..." << endl; } }; class Derived :public Base { public: /*virtual*/ void Fun1()//如果一个函数在基类中被声明为虚函数,则他在所有派生类中都是虚函数 { cout << "Derived::Fun1 ..." << endl; } /*virtual*/ void Fun2() { cout << "Derived::Fun2 ..." << endl; } void Fun3() { cout << "Derived::Fun3 ..." << endl; } Derived() { cout << "Derived ..." << endl; } ~Derived() { cout << "~Derived ..." << endl; } }; int main(void) { Base* p; p = new Derived; p->Fun1(); delete p;//当通过基类指针删除派生类对象时,如果基类析构函数不是virtual,则派生类析构函数不会调用 return 0; }
虚表指针
虚函数的动态绑定是通过虚表指针来实现的包含虚函数的类头4个字节存放指向虚表的指针
#include <iostream> using namespace std; class Base { public: virtual void Fun1() { cout << "Base::Fun1 ..." << endl; } virtual void Fun2() { cout << "Base::Fun2 ..." << endl; } int data1_; }; class Derived :public Base { public: void Fun2() { cout << "Derived::Fun2 ..." << endl; } virtual void Fun3() { cout << "Derived::Fun3 ..." << endl; } int data2_; }; typedef void(*FUNC)(); int main(void) { cout << sizeof(Base) << endl; cout << sizeof(Derived) << endl; Base b; long** p = (long**)&b; FUNC fun = (FUNC)p[0][0]; fun(); fun = (FUNC)p[0][1]; fun(); cout << endl; Derived d; p = (long**)&d; fun = (FUNC)p[0][0]; fun(); fun = (FUNC)p[0][1]; fun(); fun = (FUNC)p[0][2]; fun(); return 0; }
object slicing与虚函数
#include <iostream> using namespace std; class CObject { public: virtual void Serialize() { cout << "CObject::Serialize ..." << endl; } }; class CDocument : public CObject { public: int data1_; void func() { cout << "CDocument::func ..." << endl; Serialize(); } virtual void Serialize() { cout << "CDocument::Serialize ..." << endl; } CDocument() { cout << "CDocument" << endl; } CDocument(const CDocument& other) { cout < a6c3 < "CDocument(const CDocument& other)" << endl; } }; class CMyDoc : public CDocument { public: int data2_; virtual void Serialize() { cout << "CMyDoc::Serialize ..." << endl; } }; int main() { CMyDoc mydoc; CMyDoc* pmydoc = new CMyDoc; cout << "#1 testing" << endl; mydoc.func(); cout << "#2 testing" << endl; ((CDocument*)(&mydoc))->func(); cout << "#3 testing" << endl; pmydoc->func(); cout << "#4 testing" << endl; ((CDocument)mydoc).func();//mydoc对象强制转换为CDocument对象,向上转型 //完完全全将派生类对象转化为了基类对象,调用拷贝构造函数 return 0; }
相关文章推荐
- AM335x SPL(一)
- 免费的Flex拓扑图框架iolive
- Velocity语法
- 购物商城shopping连载(6)
- IOS 代理模式 DELEGATE
- oracle锁
- linux文件类型2
- ThreadLocal理解
- 去掉标题栏
- 表单GET 和 POST提交方式
- Erlang--节点
- 103 保序回归 isotonic regression
- 283. Move Zeroes
- Java并发概念汇总
- 1.c++笔记---有趣的bool型
- 【BZOJ 3050】【USACO2013 Jan】Seating 线段树
- 虚拟机ubunt14.04调整分辨率
- 在tomcat中部署测试Servlet(不用eclipse或MyEclipse的tomcat插件)
- Linux 远程复制
- Java的四种引用类型分析