设为首页 加入收藏

TOP

ATL布幔下的秘密之虚函数背后的东西(三)
2012-11-04 15:06:41 来源: 作者: 【 】 浏览:926
Tags:ATL 秘密 函数 背后 东西
  现在,你会发现在基类中含有多个虚函数的情况下,派生类并不能完全重写它们。

  程序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模式下,它会显示一个运行时错误的对话框:


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


  而在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 下一页 尾页 3/5/5
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇ATL布幔下的秘密之模板技术 下一篇ATL布幔下的秘密之内部工作方式

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: