c++句柄类 c 获取窗体句柄

c++句柄类 c 获取窗体句柄

代理类能让我们在一个容器中存储类型不同但相互关联的对象。创建代理将会复制所代理的对象,如果想避免这些复制该怎么办?

通常参数和返回值是通过复制自动传递的,用引用传递参数可以避免这样的复制,但是这样对返回值来说不太容易(比如局部对象)。同样可以用指针来避免复制,但是使用指针有几个问题:

(1)使用对象指针比直接使用对象要困难。

(2)未初始化的指针非常危险,在c++实现中,只要对这样的指针实施复制操作就会出现问题。

(3)无论何时,只要有几个指针指向同一个对象,就必须考虑在什么时候删除这个对象。

为了能够在保持多态性的前提下避免复制对象,c++解决方法就是定义句柄类,将句柄类的对象绑定到它们所控制的类的对象上。

一 怎样绑定? 这里有两种选择:

(1)可以创建自己的对象并把它赋给一个handle去进行复制。

有对象p, 则 Handle h(p) 将创建p的一个副本,并将handle绑定到该副本。handle可以控制对该对象副本的操作。

(2)可以把用于创建对象的参数传递给这个handle

有类Point ,创建一个对象方式为:Point p(123,456). 则Handle h(123, 456)将创建一个句柄,该句柄绑定到point(123,456)。

从效果上说,handle就是一种只包含单个对象的容器。

二 已经将句柄绑定到对象,怎样获取对象?

要是一个handle在行为上类似一个指针,则可以使用operator->将handle的所有操作都转发给相应的Point操作来执行。Point*operator->();Point * addr = h.operator->()这样就可以获取对象地址了。如果我们希望handle能够对对象的分配和回收拥有完全的控制权,则最好能够阻止用户直接获得对象的实际地址。所以,如果想把真实的地址隐藏起来,就必须避免使用operator->,而且必须明确的选择让我们的handle类支持哪些Point操作。

三 句柄类已经设计好了,它到底怎样避免对象复制的?

考虑函数传参的问题,把一个句柄作为参数传给函数,我们希望的是复制句柄而不复制对象。为此,我们必须了解有多少个句柄绑定到同一个对象上,只有这样才能确定在何时删除对象,通常使用引用计数来达到这个目的。重新设计一个引用计数类,这个类包含一个引用计数和一个Point对象,称之为UPoint。个人感觉这个UPoint就是更高一层次的抽象,以后handle只要和UPoint打交道就行了,然后由UPoint和Point打交道。UPoint的全部构造方式和Point的一样。这个类纯粹是为了实现而设计的,实际运用中根本没有这个类。因此其所有成员函数都设为私有。以下是几个类的实现代码,有详细注释:

classPoint

{

public:

Point():xval(0),yval(0){ std::cout<<"Pointcreate"<<std::endl;}

Point(int x,int y):xval(x),yval(y){ std::cout<<"Point(x,y)create"<<std::endl;}

int x() const { return xval;}

int y() const { return yval;}

Point& x(int xv) { xval=xv; return *this;}

Point& y(int yv) { yval=yv; return *this;}

~Point() { std::cout<<"~Point"<<std::endl;}

private:

int xval,yval;

};

class Handle;

//这个类对用户来说是不可见的, 就是一个间接层

class UPoint

{

//所有成员都是私有的

friend class Handle;

Point p;//Point 对象

int u;//计数器

UPoint():u(1){std::cout<<"UPoint create"<<u<<std::endl;}

UPoint(int x,int y):p(x,y),u(1){ std::cout<<"UPoint(x,y)create "<<u<<std::endl;}

UPoint(const Point& p0):p(p0),u(1){ std::cout<<"UPoint(p)create "<<u<<std::endl;}

~UPoint() { std::cout<<"~UPoint"<<u<<std::endl;}

};

class Handle

{

public:

//按创建Point的方式构造handle,handle->UPoint->Point

Handle():up(new UPoint){ std::cout<<"Handle create"<<up->u<<std::endl;}

Handle(int x,int y):up(new UPoint(x,y)){std::cout<<"Handle(x,y) create"<<up->u<<std::endl;}

Handle(const Point& p):up(new UPoint(p)){std::cout<<"Handle(p) create"<<up->u<<std::endl;}

~Handle()

{

std::cout<<"Handle number 数量减少一个 --"<<up->u-1<<std::endl;

if (--up->u == 0)

{

delete up;

std::cout<<"Handle destroy"<<std::endl;

}

}

Handle(const Handle& h):up(h.up)

{

++up->u;//此处复制的是handle,但是底层的point对象并未复制,只是引用计数加1

std::cout<<"调用Handle赋值构造函数 --"<<up->u<<std::endl;

}

Handle& operator=(const Handle& h)

{

++h.up->u;//右边的对象引用计数加1,左边的减1

if (--up->u == 0)

{

delete up;

}

up = h.up;

std::cout<<"调用Handle赋值运算符 --"<<up->u<<std::endl;

return *this;

}

int x() const

{

return up->p.x();

}

int y() const

{

return up->p.y();

}

//指针语义,改变对象

Handle& x(int x0)

{

up->p.x(x0);

return *this;

}

Handle& y(int y0)

{

up->p.y(y0);

return *this;

}

//值语义,不改变对象

//Handle& x(int x0)

//{

// if (up->u != 1)

// {

// --up->u;

// up = new UPoint(up->p);

// }

// up->p.x(x0);

// return *this;

//}

//Handle& y(int y0)

//{

// if (up->u != 1)

// {

// --up->u;

// up = new UPoint(up->p);

// }

// up->p.y(y0);

// return *this;

//}

private:

UPoint* up;//和间接层UPoint打交道了

};

测试函数

void f(Handle h) //测试函数,复制handle,但未复制Point

{

cout << h.x() << h.y() << endl;

}

int _tmain(int argc, _TCHAR* argv[])

{

{

Handle h(3,5);

cout << h.x() << h.y() << endl;

f(h);

Handle h2 = h;

cout<<h2.x()<<h2.y()<<endl;

}

getchar();

return 0;

}

测试结果


我们可以看出程序自始至终只创建了一个point对象,只有引用计数一直在增加,当引用计数减少到0后,执行point的析构函数。

  

爱华网本文地址 » http://www.aihuau.com/a/25101017/364417.html

更多阅读

学会用按键精灵获取子窗口句柄 按键精灵获取窗口句柄

学会用按键精灵获取子窗口句柄——简介电脑的桌面是最顶级的窗口,在桌面里的其他程序窗口是桌面的子窗口。那到底父窗口和子窗口是怎么理解的呢?学会用按键精灵获取子窗口句柄——工具/原料按键精灵2014学会用按键精灵获取子窗口句柄

MFC中什么叫句柄 mfc 获取控件句柄

(句柄)HANDLEexplaination from microsoft:when you went to cinema,you bring a umbrella,and you want to have the peopel in cinema to keep the umbrella for you,thn you give them the umbrella,they give you a ticket to p

delphi中TDBGrid的使用 c 句柄 tdbgrid

2010-06-24 10:03procedure TMainForm.DBGrid1DrawColumnCell(Sender: TObject;const Rect: TRect; DataCol: Integer; Column: TColumn;State: TGridDrawState);var i :integer;beginif gdSelected in State th

句类及句子的特殊成分 英语句子成分划分练习

第十三节句类及句子的特殊成分学习要点:了解现代汉语的四种句类,能区分句子的特殊成分类型。一、句类句法结构带上语气便是句子,离开了语气,便是词与词、词与短语的组合了。句子从语气上大致可分为四类:陈述句、疑问句、祈使句和感叹

C 句柄概念详解 新概念英语3练习详解

C++句柄概念详解这个句柄只是从英文handle翻译过来的,只问句是什么意思难以解释,这个是我从别人的空间收集的信息,功能上的理解:什么是"句柄"(handle),handle的本意是把柄,把手的意思。是你与操作系统打交道的东东。

声明:《c++句柄类 c 获取窗体句柄》为网友夜清冷一曲分享!如侵犯到您的合法权益请联系我们删除