友情提示:如果本网页打开太慢或显示不完整,请尝试鼠标右键“刷新”本网页!
深入浅出MFC第2版(PDF格式)-第23部分
快捷操作: 按键盘上方向键 ← 或 → 可快速上下翻页 按键盘上的 Enter 键可回到本书目录页 按键盘上方向键 ↑ 可回到本页顶部! 如果本书没有阅读完,想下次继续接着阅读,可使用上方 "收藏到我的浏览器" 功能 和 "加入书签" 功能!
class Class1 {
public :
data1;
data2;
memfunc ();
virtual vfunc1();
virtual vfunc2 ();
virtual vfunc3();
};
Class1 对象实体在内存中占据这样的空间:
77
…………………………………………………………Page 140……………………………………………………………
Class1 对象实体 vtable
vptr (*vfunc1)() Class1::vfunc1()
class Class1 m_data1 (*vfunc2)() Class1::vfunc2()
{
public : m_data2 (*vfunc3)() Class1::vfunc3()
m_data1;
m_data2; Class1::memfunc()
memfunc();
virtual vfunc1();
virtual vfunc2();
virtual vfunc3();
}
C++ C
类别的成员函数,你可以想象就是 语言中的函数。它只是被编译器改过名称,
并增加一个参数(this 指针),因而可以处理调用者(C++ 对象)中的成员变量。所以,
你并没有在Class1 对象的内存区块中看到任何与成员函数有关的任何东西。
每一个由此类别衍生出来的对象,都有这么一个vptr 。当我们透过这个对象调用虚拟函
数,事实上是透过vptr 找到虚拟函数表,再找出虚拟函数的真正地址。
奥妙在于这个虚拟函数表以及这种间接调用方式。虚拟函数表的内容是依据类别中的虚
拟函数声明次序,一一填入函数指针。衍生类别会继承基础类别的虚拟函数表(以及所
有其它可以继承的成员),当我们在衍生类别中改写虚拟函数时,虚拟函数表就受了影
响:表中元素所指的函数地址将不再是基础类别的函数地址,而是衍生类别的函数地址。
看看这个例子:
class Class2 : public Class1 {
public :
data3;
memfunc();
virtual vfunc2();
};
78
…………………………………………………………Page 141……………………………………………………………
class Class2 : public Class1
{ vtable
public : vptr (*vfunc1)() Class1::vfunc1()
m_data3;
memfunc(); m_data1 (*vfunc2)() Class2::vfunc2()
virtual vfunc2();
} m_data2 (*vfunc3)() Class1::vfunc3()
m_data3 Class2::memfunc()
Class2 对象实体
于是,一个「指向Class1 所生对象」的指针,所调用的vf unc2 就是Class1::vf unc2 ,而
一个「指向Class2 所生对象」的指针,所调用的vf unc2 就是Class2::vf unc2 。
动态绑定机制,在执行时期,根据虚拟函数表,做出了正确的选择。
我们解开了第二道神秘。
口说无凭,何不看点实际。观其地址,物焉C哉,下面是一个测试程序:
#0001 #include
#0002 #include
#0003
#0004 class ClassA
#0005 {
#0006 public:
#0007 int m_data1;
#0008 int m_data2;
#0009 void func1() { }
#0010 void func2() { }
#0011 virtual void vfunc1() { }
#0012 virtual void vfunc2() { }
#0013 };
#0014
#0015 class ClassB : public ClassA
#0016 {
#0017 public:
#0018 int m_data3;
#0019 void func2() { }
#0020 virtual void vfunc1() { }
#0021 };
#0022
#0023 class ClassC : public ClassB
#0024 {
79
…………………………………………………………Page 142……………………………………………………………
#0025 public:
#0026 int m_data1;
#0027 int m_data4;
#0028 void func2() { }
#0029 virtual void vfunc1() { }
#0030 };
#0031
#0032 void main()
#0033 {
#0034 cout
快捷操作: 按键盘上方向键 ← 或 → 可快速上下翻页 按键盘上的 Enter 键可回到本书目录页 按键盘上方向键 ↑ 可回到本页顶部!
温馨提示: 温看小说的同时发表评论,说出自己的看法和其它小伙伴们分享也不错哦!发表书评还可以获得积分和经验奖励,认真写原创书评 被采纳为精评可以获得大量金币、积分和经验奖励哦!