频道直达 - 专题 - 新闻 - 技巧 - 组网 - 开发 - 安全 - web编程 - 图像 - 操作系统 - 数据库 - 教育 - 旅游 - 健康 - 时尚 - 驱动 - 软件 - 游戏 - 多媒体 - ERP - 讨论组

ATL布幔下的秘密之虚函数背后的东西

来源:VCKBASE 作者:李马编译 出处:巧巧读书 2005-12-02 进入讨论组
上一页 1 2 3 4 5 下一页 
谢 谢 收 藏 http://www.qqread.com/vc/n782121200.html
  现在,你会发现在基类中含有多个虚函数的情况下,派生类并不能完全重写它们。

  程序26.

#include <iostream>
using namespace std;

class Base {
 public:
 Base() {
  cout << "In Base" << endl;
  cout << "Virtual Pointer = " << (int*)this << endl;
  cout << "Address of Vtable = " << (int*)*(int*)this << endl;
  cout << "Value at Vtable 1st entry = " << (int*)*((int*)*(int*)this+0) << endl;
  cout << "Value at Vtable 2nd entry = " << (int*)*((int*)*(int*)this+1) << endl;
  cout << "Value at Vtable 3rd entry = " << (int*)*((int*)*(int*)this+2) << endl;
  cout << endl;
 }
 virtual void f1() { cout << "Base::f1" << endl; }
 virtual void f2() { cout << "Base::f2" << endl; }
};

class Drive : public Base {
 public:
 Drive() {
  cout << "In Drive" << endl;
  cout << "Virtual Pointer = " << (int*)this << endl;
  cout << "Address of Vtable = " << (int*)*(int*)this << endl;
  cout << "Value at Vtable 1st entry = " << (int*)*((int*)*(int*)this+0) << endl;
  cout << "Value at Vtable 2nd entry = " << (int*)*((int*)*(int*)this+1) << endl;
  cout << "Value at Vtable 3rd entry = " << (int*)*((int*)*(int*)this+2) << endl;
  cout << endl;
 }
 virtual void f1() { cout << "Drive::f1" << endl; }
};

int main() {
 Drive d;
 return 0;
}

  程序的输出为:

In Base
Virtual Pointer = 0012FF7C
Address of Vtable = 0046C0E0
Value at Vtable 1st entry = 004010F0
Value at Vtable 2nd entry = 00401145
Value at Vtable 3rd entry = 00000000

In Drive
Virtual Pointer = 0012FF7C
Address of Vtable = 0046C0C8
Value at Vtable 1st entry = 0040121C
Value at Vtable 2nd entry = 00401145
Value at Vtable 3rd entry = 00000000

  这个程序的输出表明基类的虚函数在派生类中并未被重写,然后,派生类的构造函数没有对虚函数的入口做任何的事情。
  
  那么现在,让我邀请纯虚函数来加入这一游戏,再来看看它的行为吧。请看以下的程序:

  程序27.

#include <iostream>
using namespace std;

class Base {
 public:
 Base() {
  cout << "In Base" << endl;
  cout << "Virtual Pointer = " << (int*)this << endl;
  cout << "Address of Vtable = " << (int*)*(int*)this << endl;
  cout << "Value at Vtable 1st entry = " << (int*)*((int*)*(int*)this+0) << endl;
  cout << "Value at Vtable 2nd entry = " << (int*)*((int*)*(int*)this+1) << endl;
  cout << endl;
 }
 virtual void f1() = 0;
 virtual void f2() = 0;
};

class Drive : public Base {
 public:
 Drive() {
  cout << "In Drive" << endl;
  cout << "Virtual Pointer = " << (int*)this << endl;
  cout << "Address of Vtable = " << (int*)*(int*)this << endl;
  cout << "Value at Vtable 1st entry = " << (int*)*((int*)*(int*)this+0) << endl;
  cout << "Value at Vtable 2nd entry = " << (int*)*((int*)*(int*)this+1) << endl;
  cout << endl;
 }
 virtual void f1() { cout << "Drive::f1" << endl; }
 virtual void f2() { cout << "Drive::f2" << endl; }
};

int main() {
 Drive d;
 return 0;
}

  在debug和release模式下,程序的输出有所不同。下面是debug模式的输出:

In Base
Virtual Pointer = 0012FF7C
Address of Vtable = 0046C0BC
Value at Vtable 1st entry = 00420CB0
Value at Vtable 2nd entry = 00420CB0

In Drive
Virtual Pointer = 0012FF7C
Address of Vtable = 0046C0A4
Value at Vtable 1st entry = 00401212
Value at Vtable 2nd entry = 0040128F

  以下则是release模式的输出:

In Base
Virtual Pointer = 0012FF80
Address of Vtable = 0042115C
Value at Vtable 1st entry = 0041245D
Value at Vtable 2nd entry = 0041245D

In Drive
Virtual Pointer = 0012FF80
Address of Vtable = 00421154
Value at Vtable 1st entry = 00401310
Value at Vtable 2nd entry = 00401380

  为了更好地弄懂这一原理,我们需要对程序作少许的改动,并尝试使用函数指针来调用虚函数。

  程序28.

#include <iostream>
using namespace std;

typedef void(*Fun)();

class Base {
 public:
 Base() {
  cout << "In Base" << endl;
  cout << "Virtual Pointer = " << (int*)this << endl;
  cout << "Address of Vtable = " << (int*)*(int*)this << endl;
  cout << "Value at Vtable 1st entry = " << (int*)*((int*)*(int*)this+0) << endl;
  cout << "Value at Vtable 2nd entry = " << (int*)*((int*)*(int*)this+1) << endl;

  // 尝试执行第一个虚函数
  Fun pFun = (Fun)*((int*)*(int*)this+0);
  pFun();

  cout << endl;
 }
 virtual void f1() = 0;
 virtual void f2() = 0;
};

class Drive : public Base {
 public:
 Drive() {
  cout << "In Drive" << endl;
  cout << "Virtual Pointer = " << (int*)this << endl;
  cout << "Address of Vtable = " << (int*)*(int*)this << endl;
  cout << "Value at Vtable 1st entry = " << (int*)*((int*)*(int*)this+0) << endl;
  cout << "Value at Vtable 2nd entry = " << (int*)*((int*)*(int*)this+1) << endl;
  cout << endl;
 }
 virtual void f1() { cout << "Drive::f1" << endl; }
 virtual void f2() { cout << "Drive::f2" << endl; }
};

int main() {
 Drive d;
 return 0;
}

  现在程序的行为在debug和release模式下仍然不同。在debug模式下,它会显示一个运行时错误的对话框:

ATL布幔下的秘密之虚函数背后的东西

  并且,当你按下“忽略”按钮之后,它会显示下面的对话框:

ATL布幔下的秘密之虚函数背后的东西

  而在release模式下运行的话,它只会在控制台窗口中输出错误信息:

In Base
Virtual Pointer = 0012FF80
Address of Vtable = 0042115C
Value at Vtable 1st entry = 0041245D
Value at Vtable 2nd entry = 0041245D

runtime error R6025
- pure virtual function call

进入讨论组讨论。
更多专题 【深 度 阅 读】 相 关 文 章
    上一页 1 2 3 4 5 下一页 
    收藏此文】【 】【打印】【关闭
    相关图文阅读
    频道图文推荐
    健 康 咨 询
    时 尚 咨 询
    巧巧读书宗旨
    相关专题
    讨论组问题推荐
    站内各频道最新更新文档
    站内最新制作专题
    热门关键字导读
    Photoshop教 程照片处理 照片制作 PS快捷键 抠图
    计 算 机 故 障XP系统修复
    艺 术 与 设 计设计 流媒体 设计欣赏 边框
    计 算 机 安 全ARP
    站内频道文章精选
    巧巧电脑频道编辑信箱  告诉我们您想看的专题或文章