读书笔记(4)

 

GDI/DirectDraw内部数据结构(一)

句柄和面向对象的编程

(1)Win32 API中的对象可以认为是使用没有数据成员的抽象基类实现的。对象的数据表示对用户应用程序是完全隐蔽的,这样可以大

 

大改善了程序的可移植性。下面是C++中的GDI伪执行:

//gdi.h

class _GdiObj

{

public:

virtual int GetObjectType() = 0;

virtual int GetObject(int cbBuffer,void * pBuffer) = 0;

virtual bool DeleteObject() = 0;

virtual bool UnrealizeObject() = 0;

};

 

class _Pen : public _GdiObj

{

public:

virtual int GetObjectType()

{

return OBJ_PEN;

}

 

virtual int GetObject(int cbBuffer,void * pBuffer) = 0;

virtual bool DeleteObject() = 0;

virtual bool UnrealizeObject()

{

return true;

}

};

 

_Pen * _CreatePen(int fnPenStyle,int nWidth,COLORREF crColor);

 

//gdi.cpp

#define STRICT

#define WIN32_LEAN_AND_MEAN

#include <windows.h>

#include "gdi.h"

 

class _RealPen : public _Pen

{

LOGPEN m_LogPen;

 

public:

_RealPen(int fnPenStyle,int nWidth,COLORREF crColor)

{

m_LogPen.lopnStyle = fnPenStyle;

m_LogPen.lopnWidth.x = nWidth;

m_LogPen.lopnWidth.y = 0;

m_LogPen.lopnColor = crColor;

}

 

int GetObject(int cbBuffer,void * pBuffer)

{

if(pBuffer == NULL)

            return sizeof(LOGPEN);

else if(cbBuffer >= sizeof(m_LogPen))

{

memcpy(pBuffer,&m_LogPen,sizeof(m_LogPen));

return sizeof(LOGPEN);

}

else

{

SetLastError(ERROR_INVALID_PARAMETER);

return 0;

}

}

 

bool DeleteObject()

{

if(this)

{

delete this;

return true;

}

else

return false;

}

};

 

_Pen *_CreatePen(int fnPenStyle,int nWidth,COLORREF crColor)

{

return new _RealPen(fnPenStyle,nWidth,crColor);

}

 

//test.cpp

void Test()

{

_Pen *pPen = _CreatePen(PS_SOLID,1,RGB(0,0,0xEF));

pPen->DeleteObject();

}

 

上面的程序用_GdiObj类为常用GDI对象定义了抽象基类。它只有四个纯虚函数,没有数据成员。通用画笔类_Pen从_GdiObj派生。它

 

实现了两个虚函数并让剩下的两个函数仍是纯虚函数。它提供了CreatePen例程来创建Pen类的实例。在实现文件( GDI.cpp)中,真

 

正的画笔类(_RealPen)使用LOGPEN结构存储关于画笔的信息。它完全实现了抽象类_Pen,实现了一个构造函数和剩下的两个纯虚函

 

数。_CreatePen例程式创建_RealPen类的实例,并把它的指针作为通用画笔类_Pen的指针传入.

 

(2)指针与句柄:在面向对象评议中创建对象,需要分配一块保存对象成员变量的内在。如果它的类有虚函数,就要再分配一个额外的

 

指针,并将它赋值成指向该类所有虚函数实现全程表的指针。在C++这样的语言中,指向对象的指针很重要。它被传递给该类的所有

 

非静态成员函数,这样才能访问该对象的数据成员,调用正确的虚函数。这样的指针被称为C++中的"this"指针。

上面程序所示的_RealPen类说明了对象指针所指的内容。对于_RealPen类,需要用16个字节存储唯一的数据成员m_LogPen,4个字节存

 

储vtable(虚函数表)指针。因此每个对象至少要分配20个字节。 vtable指针指向一个有4个函数指针的表。在这种情况下,其中两个

 

函数是在_Pen类实现,加外两个函数由_RealPen类实现。

 

 

(3)为了对程序员进一步隐藏,Win32对象创建例程一般不是返回指针,因为指针包含了太多信息。它给出了对象存储的确切位置。指

 

针一般允许对对象的内部表示进行读/写操作,而这些内部表示也许正是操作系统想隐藏的。所以Win32对象创建例程一般返回对象句

 

柄。句柄可以映射为唯一标识对象的值,或者是对象的间接引用。更准确地说,句柄是和对象一一对应的值。对象可以映射到唯一的

 

句柄,句柄也能够映射到唯一的对象。为了保证句柄能够完成信息隐藏的任务,对象和句柄之间映射的没有文档记载,不保证固定不

 

变,而且仅有微软知道这种映射,或者还有少数系统级工具的开发商知道。

 

(4)在极端的情况下,句柄可以和对象指针相同,其之间的映射为全等映射。

(5)对象指针和句柄之间映射最普通的机制是基于表格的映射。

(6)只有句柄是不够的,尽管句柄提供了近乎完美的抽象、信息隐藏和保护,但它也是程序员遭受挫折的地方。在像Win32 API这样以

 

句柄为中心的API中,微软没有文档记载对象的内部表示以及对象是如何管理的,也没有提供参考实现程序员只有函数原型、微软文

 

档和或多或少基于微软文档之上的书籍。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值