Chinaunix首页 | 论坛 | 博客
  • 博客访问: 16498196
  • 博文数量: 5645
  • 博客积分: 9880
  • 博客等级: 中将
  • 技术积分: 68081
  • 用 户 组: 普通用户
  • 注册时间: 2008-04-28 13:35
文章分类

全部博文(5645)

文章存档

2008年(5645)

我的朋友

分类:

2008-04-28 20:58:16

下载本文示例代码
  介绍   在本系列的教程中,我要讨论一些ATL的内部工作方式以及它所使用的技术,这是本系列的第二篇文章。   现在让我们来探究一些虚函数背后更加有趣的资料。为了和上文保持一致,在本文的讨论中我将使用相同的顺序,程序的序号从20开始。  让我们看看下面这个程序:   程序20. #include <iostream>using namespace std;class Base { public:  virtual void fun() {   cout << "Base::fun" << endl;  }  void show() {   fun();  }};class Drive : public Base { public:  virtual void fun() {   cout << "Drive::fun" << endl;  }};int main() { Drive d; d.show(); return 0;}  程序的输出为:Drive::fun  这个程序清楚地示范了基类的函数是如何调用派生类的虚函数的。这一技术被用于不同的框架中,例如MFC和设计模式(比如Template Design Pattern)。现在你可以修改一下这个程序来看看它的行为,我将要在基类的构造函数中调用虚函数,而不是普通的成员函数。   程序21. #include <iostream>using namespace std;class Base { public:  Base() {   fun();  } virtual void fun() {  cout << "Base::fun" << endl; }};class Drive : public Base {public: virtual void fun() {  cout << "Drive::fun" << endl; }};int main() { Drive d; return 0;}  程序的输出为:ase::fun  这个程序表明,我们不能在基类的构造函数中调用派生类的虚函数。好了,那就让我们来看看着布幔之下到底做了什么。我将会把这些构造函数之中的指针值打印出来,为了简便起见,我移除了类中其它的函数。   程序22. #include <iostream>using namespace std;class Base { public:  Base() {   cout << "In Base" << endl;   cout << "This Pointer = " << (int*)this << endl;   cout << endl;  }  virtual void f() { cout << "Base::f" << endl; } };class Drive : public Base { public: Drive() {  cout << "In Drive" << endl;  cout << "This Pointer = " << (int*)this << endl;  cout << endl; } virtual void f() { cout << "Drive::f" << endl; }};int main() { Drive d; cout << "In Main" << endl; cout << (int*)&d << endl; return 0;}  程序的输出为: In BaseThis Pointer = 0012FF7CIn DriveThis Pointer = 0012FF7CIn Main0012FF7C  这就表示,整个内存位置中,只有一个对象的存在。那么就让我们把这个指针指向的值打印出来,也就是虚函数表的指针vptr指向的值,VTable的地址。   程序23. #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 = " << (int*)*(int*)*(int*)this << endl;  cout << endl; } virtual void f1() { cout << "Base::f1" << 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 = " << (int*)*(int*)*(int*)this << endl;  cout << endl; } virtual void f1() { cout << "Drive::f2" << endl; }};int main() { Drive d; return 0;}  程序的输出为: In BaseVirtual Pointer = 0012FF7CAddress of Vtable = 0046C08CValue at Vtable = 004010F0In DriveVirtual Pointer = 0012FF7CAddress of Vtable = 0046C07CValue at Vtable = 00401217  这个程序示范了基类和派生类中不同的虚函数表地址。为了更好地弄懂这一问题,那就让我们把继承层次加深,并添加一个继承于Drive类的MostDrive类,然后构建一个它的对象。 共5页。 1 2 3 4 5 :   介绍   在本系列的教程中,我要讨论一些ATL的内部工作方式以及它所使用的技术,这是本系列的第二篇文章。   现在让我们来探究一些虚函数背后更加有趣的资料。为了和上文保持一致,在本文的讨论中我将使用相同的顺序,程序的序号从20开始。  让我们看看下面这个程序:   程序20. #include <iostream>using namespace std;class Base { public:  virtual void fun() {   cout << "Base::fun" << endl;  }  void show() {   fun();  }};class Drive : public Base { public:  virtual void fun() {   cout << "Drive::fun" << endl;  }};int main() { Drive d; d.show(); return 0;}  程序的输出为:Drive::fun  这个程序清楚地示范了基类的函数是如何调用派生类的虚函数的。这一技术被用于不同的框架中,例如MFC和设计模式(比如Template Design Pattern)。现在你可以修改一下这个程序来看看它的行为,我将要在基类的构造函数中调用虚函数,而不是普通的成员函数。   程序21. #include <iostream>using namespace std;class Base { public:  Base() {   fun();  } virtual void fun() {  cout << "Base::fun" << endl; }};class Drive : public Base {public: virtual void fun() {  cout << "Drive::fun" << endl; }};int main() { Drive d; return 0;}  程序的输出为:ase::fun  这个程序表明,我们不能在基类的构造函数中调用派生类的虚函数。好了,那就让我们来看看着布幔之下到底做了什么。我将会把这些构造函数之中的指针值打印出来,为了简便起见,我移除了类中其它的函数。   程序22. #include <iostream>using namespace std;class Base { public:  Base() {   cout << "In Base" << endl;   cout << "This Pointer = " << (int*)this << endl;   cout << endl;  }  virtual void f() { cout << "Base::f" << endl; } };class Drive : public Base { public: Drive() {  cout << "In Drive" << endl;  cout << "This Pointer = " << (int*)this << endl;  cout << endl; } virtual void f() { cout << "Drive::f" << endl; }};int main() { Drive d; cout << "In Main" << endl; cout << (int*)&d << endl; return 0;}  程序的输出为: In BaseThis Pointer = 0012FF7CIn DriveThis Pointer = 0012FF7CIn Main0012FF7C  这就表示,整个内存位置中,只有一个对象的存在。那么就让我们把这个指针指向的值打印出来,也就是虚函数表的指针vptr指向的值,VTable的地址。   程序23. #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 = " << (int*)*(int*)*(int*)this << endl;  cout << endl; } virtual void f1() { cout << "Base::f1" << 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 = " << (int*)*(int*)*(int*)this << endl;  cout << endl; } virtual void f1() { cout << "Drive::f2" << endl; }};int main() { Drive d; return 0;}  程序的输出为: In BaseVirtual Pointer = 0012FF7CAddress of Vtable = 0046C08CValue at Vtable = 004010F0In DriveVirtual Pointer = 0012FF7CAddress of Vtable = 0046C07CValue at Vtable = 00401217  这个程序示范了基类和派生类中不同的虚函数表地址。为了更好地弄懂这一问题,那就让我们把继承层次加深,并添加一个继承于Drive类的MostDrive类,然后构建一个它的对象。 共5页。 1 2 3 4 5 : 下载本文示例代码


ATL布幔下的秘密之虚函数背后的东西ATL布幔下的秘密之虚函数背后的东西ATL布幔下的秘密之虚函数背后的东西ATL布幔下的秘密之虚函数背后的东西ATL布幔下的秘密之虚函数背后的东西ATL布幔下的秘密之虚函数背后的东西ATL布幔下的秘密之虚函数背后的东西ATL布幔下的秘密之虚函数背后的东西ATL布幔下的秘密之虚函数背后的东西ATL布幔下的秘密之虚函数背后的东西ATL布幔下的秘密之虚函数背后的东西ATL布幔下的秘密之虚函数背后的东西ATL布幔下的秘密之虚函数背后的东西ATL布幔下的秘密之虚函数背后的东西ATL布幔下的秘密之虚函数背后的东西
阅读(146) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~