科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网软件频道基础软件ATL布幔下的秘密之内部工作方式

ATL布幔下的秘密之内部工作方式

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

在本系列的教程中,我要讨论一些ATL的内部工作方式以及它所使用的技术。

作者:李马编译 来源:VCKBASE 2007年10月19日

关键字:

  • 评论
  • 分享微博
  • 分享邮件
程序6.

#include <iostream>
using namespace std;

class CPoint {
public:
int m_ix;
int m_iy;
virtual ~CPoint() { } // 译注:原文此处有分号,我将其去掉,下皆同
};

int main() {
CPoint objPoint;
cout << "Size of Class = " << sizeof(objPoint) << endl;
cout << "Address of Class = " << &objPoint << endl;
return 0;
}

  程序的输出为:

Size of Class = 12
Address of Class = 0012FF68

  这些程序的输出表明,当你向类中添加了虚函数之后,那么它的尺寸就会增加一个int的大小。在Visual C++中也就是增加4个字节。这就意味着这个类中有三个整数大小的位置,一个是x,一个是y,另一个是处理虚函数之用的虚函数表指针。首先,让我们来看看这个新的位置,也就是这个位于对象首部(或末尾)的虚函数表指针。要这么做的话,我们需要直接存取对象所占用的内存。我们可以使用神奇的指针技术,即用一个指向int的指针来存储一个对象的地址。

  程序7.

#include <iostream>
using namespace std;

class CPoint {
public:
int m_ix;
int m_iy;
CPoint(const int p_ix = 0, const int p_iy = 0) :
m_ix(p_ix), m_iy(p_iy) {
}
int getX() const {
return m_ix;
}
int getY() const {
return m_iy;
}
virtual ~CPoint() { }
};

int main() {
CPoint objPoint(5, 10);

int* pInt = (int*)&objPoint;
*(pInt+0) = 100; // 企图改变x的值
*(pInt+1) = 200; // 企图改变y的值

cout << "X = " << objPoint.getX() << endl;
cout << "Y = " << objPoint.getY() << endl;

return 0;
}

  这个程序中最重要的东西是:

int* pInt = (int*)&objPoint;
*(pInt+0) = 100; // 企图改变x的值
*(pInt+1) = 200; // 企图改变y的值

  其中,我们在把对象的地址存入一个整型指针之后,就可以把这个对象看作一个整型的指针了。程序的输出为:

X = 200
Y = 10

  当然,这并不是我们想要的结果,它表明200存储在了m_ix数据成员的位置。这就意味着m_ix,也就是第一个成员变量,是起始于内存中第二个位置的,而不是第一个。换句话说,第一个成员是虚函数表指针,其它的才是对象的数据成员。那么,只需要修改以下的两行:

int* pInt = (int*)&objPoint;
*(pInt+1) = 100; // 企图改变x的值
*(pInt+2) = 200; // 企图改变y的值

  这样我们就会获得想要的结果了,以下为完整程序:

  程序8.

#include <iostream>
using namespace std;

class CPoint {
public:
int m_ix;
int m_iy;
CPoint(const int p_ix = 0, const int p_iy = 0) :
m_ix(p_ix), m_iy(p_iy) {
}
int getX() const {
return m_ix;
}
int getY() const {
return m_iy;
}
virtual ~CPoint() { }
};

int main() {
CPoint objPoint(5, 10);

int* pInt = (int*)&objPoint;
*(pInt+1) = 100; // 企图改变x的值
*(pInt+2) = 200; // 企图改变y的值

cout << "X = " << objPoint.getX() << endl;
cout << "Y = " << objPoint.getY() << endl;

return 0;
}

  并且,程序的输出为:

X = 100
Y = 200

  下图清楚地示范了当我们向类中添加了虚函数之后,虚函数表指针就会被添加在内存结构中的第一个位置。


  现在问题出现了:虚函数表指针中到底存储了什么?那么看看下面的程序:
    • 评论
    • 分享微博
    • 分享邮件
    邮件订阅

    如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

    重磅专题
    往期文章
    最新文章