电脑桌面
添加盘古文库-分享文档发现价值到电脑桌面
安装后可以在桌面快捷访问

VC类定义范文

来源:漫步者作者:开心麻花2025-09-191

VC类定义范文(精选8篇)

VC类定义 第1篇

VC++怎样定义类对象

如果你定义了一个类(假设是A)那么声明一个A的对象的方法就是:

A a;// a 就是一个A的对象

A *a;// a 就是一个A的对象的指针

A a[N];// a 就是一个A的对象的数组

A fuctionName();// 返回A的一个对象的函数

上面是说如何定义对象,下面说如何定义一个类

最基本的:(运用关键字class)

class A{

public://公有变量及函数(没声明是public,private,protected的都默认为public,这个与Java是不同的,后者默认为protected)(可以在任意位置被访问)

......private://私有变量及函数(只能在类里面被访问)

......protecte://受保护的变量及函数(可以在派生类中被访问)

};//注意分号

一般构造函数,析构函数,复制构造函数都是在public里被声明的(不用我说什么是构造函数(construct)和什么是析构函数(destruct)了吧)。

更往深一层会有派生类,友元类,抽象类的概念。

派生类就是有一个已经存在的类来derive一个新的类,一般新的类跟原来的是被包含与包含的关系(否则声明一个派生类就没什么意义)具体实现如下:

class A: public B{

......//跟一个普通的类没什么区别

}

声明一个友元类是这样的:

class A: {

friend B

......}(A就成了B的友元类,友元函数的声明也类似)

不过要注意到,友元函数、友元类的大量使用破坏了类里的数据及函数的稳定性,或是可靠性。使得private类型的都可能被篡改。

最后抽象类:

它是通过虚函数来实现的,所谓虚函数就是加上virtual关键字在前面的函数;含有虚函数的类就是抽象类,注意到如果要实现一个函数的动态绑定对象必须要以地址的形式来传递。好吧,短短几句是不能把声明类的注意事项说清楚的,太多了(像什么封装,继承,抽象)。不过,你只要多编写多看书就会的。

VC类定义 第2篇

2014-02-02python动态加载变量示例分享

-04-04Python的lambda匿名函数的简单介绍

2013-11-11Python读写Excel文件的实例

2014-04-04使用Python获取CPU、内存和硬盘等windowns系统信息的2个例子

-10-10python 中文字符串的处理实现代码

2014-06-06Python对两个有序列表进行合并和排序的例子

2014-03-03python使用cookielib库示例分享

2013-12-12python切换hosts文件代码示例

VC类定义 第3篇

首先通过插入属性页对话框,建立三个属性页对话框资源,分别用来显示道的属性IDD_DaoPage,曲线属性IDD_CurvePage,和坐标属性IDD_AxisPage。给每一个对话分别关联一个类CDaoPage,CCurvePage,CAxisPage,基类均为CPropertyPage,并建立该类的对象:

再定义两个属性表单类对象:

当双击对话框左侧的树形控件节点后,首先通过树控件的函数GetItemText获取被双击节点的内容,然后判断双击的是道节点还是曲线节点,以曲线节点被双击为例属性页的显示步骤如下:

首先判断在双击节点之前显示的是道的属性页还是曲线的属性页,如果是曲线的属性页则无需更改属性页的显示,只需将对应节点的数据属性更新到属性页中的编辑框中即可,否则需要更新显示为曲线的属性页,程序如下:

显示完成之后如图1,这个属性页上有两个选项卡“坐标属性”和“曲线属性”,用户可以通过点击这两个选项卡分别观察此节点的属性信息。

2 曲线、坐标和道属性的保存

上面的对话框中,当用户点击树控件的节点进入对应曲线的属性,及坐标和曲线所在道的属性时,属性页对话框更新显示为对应曲线名的所有属性。此时用户可以对属性进行更改,比如曲线的颜色,线型,刻度类型等,更改完这些属性后,用户切换到另一曲线的属性显示时,就要对先前更改的对应曲线的属性进行保存,这样软件才能根据保存后的值进行曲线的更新显示。对于曲线属性的保存通过自定义的动态结构体数组来实现,以“道”的属性保存为例:

在文档类的头文件中定义曲线,轴和道的结构体对象PSTRU_DAOPAGEStruDaoPage;//定义道的结构体指针,当打开数据后,根据读入的曲线的条数和应该建立的道的个数,建立动态数组如StruDaoPage=new STRU_DAOPAGE[8];每个结构体变量中都保存一个对应道的所有属性值。

当用°户从树控件的一个项目切换到另一个项目,如从“道1”切换到曲线i,则首先应该在道属性页的OnKillActive()函数中,保存“道1”的属性值从控件关联变量到STRU_DAOPAGE[1]结构体中,然后再在曲线属性对话框的OnSetActive()函数中,将存放对应曲线属性值的结构体STRU_CURVE[i]中的值赋值到对应的控件关联变量中,再更新控件显示即可。

参考文献

[1]孙鑫,余安平.VC++深入详解[M].电子工业出版社:271-273.

术语定义的聚类研究 第4篇

术语定义的聚类研究

张 榕

(北京语言大学汉语速成学院,北京 100083)

术语定义的领域聚类是一项较新的研究课题。本文采用自下而上的层级聚类的方法,基于知网进行语义相似度计算,并根据不同词类对领域区分的贡献度以及构建领域聚类特有的停用词表来进行聚类的特征项选取,实现了术语定义的领域聚类。实验取得了较好的聚类结果。

术语,术语定义,语义相似度,领域聚类

一 前言

新事物、新概念的出现带来了大量的术语及术语定义。对术语定义进行分类加工,按领域划分为不同的类别,有利于领域学科专家建立领域术语数据库,以及系统地研究领域术语之间的概念层次关系、语义关系,提高术语检索的准确率与知识的系统化加工的效率。

由于术语在领域之间的相互借用,使得有些术语可以在多个应用领域被使用,这些术语在不同的领域具有不同的义项。以“病毒”这一术语为例,“病毒”可以是生物领域的“病毒”,也可以是计算机领域的“病毒”,而两个领域的“病毒”显然是不同的义项,当有若干条“病毒”定义时,如何从中鉴别出哪些是生物领域的病毒定义,哪些是计算机领域的病毒定义,需要人工的参与。我们以几组同名术语定义为例来阐述术语定义领域聚类的必要性。例如:

1.病毒

病毒是一种可以在其他生物体间传播并感染生物体的微小生物,一般包含核酸以及外壳蛋白,有些动物的病毒的外面也偶尔覆盖一层细胞膜。

计算机病毒是指编制或者在计算机程序中插入的破坏计算机功能或者毁坏数据,影响计算机使用,并能自我复制的一组计算机指令或者程序。

2.防火墙

防火墙:用于将因特网的子网与因特网的其余部分相离,以达到网络和信息安全效果的软件或硬体设施。

防火墙:两所房子之间或者一所房屋的两个部分之间的厚而高的墙,可以防止火灾蔓延。

3.蠕虫

蠕虫是指一种可以不断复制自己并在网络中传播的程序。

蠕虫是无脊椎动物的一大类,构造比腔肠动物复杂,身体长行,左右对称,质柔软,没有骨骼,没有脚。

4.树

树是指生成语法采用的一种二维图形表示,能方便地显示由一组规则生成句子的内部层级结构。

树是木本植物的统称。

例 1中的“病毒”分别是生物领域的术语和计算机领域的术语;例2中的“防火墙”分别是计算机领域的术语和建筑领域的术语;例3中的“蠕虫”是属于计算机领域的术语和生物领域的术语;例 4中的“树”分别是计算机领域的术语和通用领域的词语。

在领域数据库的构建和用户的使用过程中,有必要将这些定义区分开来。通过聚类将计算机科学术语聚合在一起,将生物学术语聚合在一起。但是当待处理的数据足够庞大时,人工将这些术语定义进行领域分类,将耗费大量的人力、物力,因此本文提出了计算机自动处理的术语定义的领域聚类方法。

二 术语定义聚类的流程

聚类是知识发现的重要方法,通过聚类,能够发现事物的内部规律和特征。聚类没有事先预定的类别,类别数在聚类过程中自动生成,无需人工标注和预先训练分类器。聚类作为一种无监督的机器学习方法,具有较高的灵活性和自动化处理能力[1]。本文聚类的具体过程如下图所示:

图 1 术语定义聚类流程图

三 特征项选取

术语定义集,由汉语词法分析器 I CTCLAS进行分词和词性标注,进入特征项选取阶段。术语定义聚类的过程是将相似的一组定义归为一类,如何将术语定义的文本内容转换成计算机可处理的形式,从而用于计算定义之间的相似度是整个聚类过程的关键。

本文通过将术语定义用词与普通文本用词对比发现,术语定义中的名词与普通文本中的名词具有很大的差别。在领域的判别过程中,定义句子中的名词起到的支持作用最大。考察其他词性的词语在两种文体上用词的区别,发现术语定义中的动词与普通文本中的动词的差别相对较小一些,但依然具有领域的区分度,应该作为聚类的特征,这些词性对术语定义的领域所属类别的判定,也起到了一定的贡献作用。形容词、副词对领域聚类的贡献度不大,不作为聚类的特征。

1.名词的领域区分度

术语定义的领域分类,也就是将被定义的术语做一个领域分类,被定义项属于什么领域,那么该术语定义就属于什么领域。术语在词性上大都是名词或者名词短语。定义句子中的名词对区分被定义项属于哪个领域具有最大的支持度。比如:

“卵磷脂是血管的清道夫:能将附着在血管壁上的胆固醇,中性脂肪乳化成微粒子,溶于血液中并运回肝脏而被代谢,从而改善血清脂质,清除过氧化物,使血液中胆固醇及中性脂肪含量降低,防止由胆固醇引起的血管内膜损伤。”

“胆固醇是体内最丰富的固醇类化合物,它既作为细胞生物膜的构成成分,又是类固醇类激素、胆汁酸及维生素 d的前体物质。”

“核酸是细胞内的生物大分子,是细胞的核心物质,由脱氧核糖核酸 (DNA)和核糖核酸 (RNA)组成。”

上面三个定义中的“血管”“肝脏”“细胞”“生物”“分子”“维生素”等词对领域聚类起到了绝对的支持作用。

2.动词的领域区分度:

“语音信号处理是指语音信号输入计算机后对其进行分析处理的过程,语音通过话筒转换成电信号,再经放大或转换变成数字信号,用模式分类方法分析和识别这些信号。”

“二值化是指把一组数据按一定的规则映射为0或 1的过程。”

“汉字信息处理是指用计算机对汉字表示的信息进行操作和加工,如汉字的输入、存储、识别、生成和输出等。”

上面三个句子中的动词“输入”“分析”“处理”“转化”“识别”“映射”“操作”“加工”“存储”“生成”“输出”对领域类型判别,起到了支持作用。

连词、介词和虚词对领域聚类几乎不起任何的作用,因此也可以认定,这些词性的词不具有领域区分度。

另外,还有一些词语不具有领域区分度,比如“所谓”“也就是”等等,这些作为停用词存在。

由于本文的目的是将术语定义按照领域聚类,所以特征项的选取,与普通文本聚类有所区别。我们通过停用词过滤以及定义用词的词性过滤将对领域聚类贡献极小的词语过滤掉,不参与到聚类的计算。

四 定义相似度的计算

术语定义领域聚类的本质就是通过计算术语定义之间的句子相似度,将句子相似度高的术语定义划分为一类,将相似度低的句子划分到不同的类。相似度是一个很复杂的概念,不同应用领域对相似度有不同的界定。相似度计算的常用方法有基于向量空间模型的 TF/ IDF方法以及基于语义的方法。向量空间模型的方法把文本看成为词的线性序列,不考虑词语之间的相互关系,不对语句进行语法结构分析,只考虑了利用句子的表层信息;而基于语义的方法则是对文本进行语义分析,属于深层结构分析法[2]。

本文的聚类方法是基于语义相似度,在计算相似度的过程中,将句子作为一个词语的集合进行处理。这样句子的相似度计算就转化为集合之间的相似度计算。本文采用刘群的集合相似度的计算方法[3]来计算句子的相似度:

其中m、n表示两个句子中词汇集合的大小, a、b分别表示两个句子中对应的词。对于没有建立起对应关系的词,我们赋给它一个很小的值σ作为它与空元素的相似度。通过上面的公式,定义的相似度计算转化为定义中出现的词语的相似度计算。

词语的相似度受到词语的词法、句法、语义、语用各个因素的影响。聚类的目的是把分属不同领域的句子按领域聚类,显然语义的因素对词语和句子相似度的影响最大。词义相似度计算是自然语言处理中一个重要的研究方向,被应用在文本分类、信息检索、词义排歧等领域。我们使用董振东先生创建的知网 (HowNet)作为语义知识资源库,进行语义之间的相似度计算[4-5]。按照知网的定义,概念是对词汇语义的一种描述。一个词汇可能表示多种概念,而每个概念可以分解为若干义原,义原是用于描述一个概念的最基本的、不能再分割意义的最小单位。

若有两个词语W1和W2,如果W1有 m个概念,W2有 n个概念:s11m,s12…stm,则两个词语之间的相似度,由这两个词之间所有概念之间的相似度的最大值来决定,用公式表示为:

通过上述公式,词语之间的相似度计算就转化为概念之间的相似度计算。

知网的每个概念由多个义原来描述:

1)第一基本义原描述:两个概念的基本义原的相似度为 Sim1(S1,S2);

2)其他基本义原描述:是一个除第一基本义原以外基本义原的集合,其他基本义原相似度为Sim2(S1,S2);

3)关系义原描述:是一个特征结构,对于该特征结构的每一个特征,属性是一个关系义原,值是一个基本义原,或一个具体词。关系义原描述的相似度为 Sim3(S1,S2);

4)关系符号描述:是一个特征结构,对于该特征结构的每一个特征,属性是一个关系义原,值是一个集合,该集合的元素是一个基本义原,或一个具体词。关系符号描述的相似度为 S im4(S1,S2)。

这样,两个概念语义表达式的整体相似度记为:

其中βi(1≤i≤4)是可调节的参数,且有:

第一基本义原是概念最主要的特征,所以权值最高,其他的特征赋予一个递减的权重。

若有两个义原 S1,S2,其相似度记为 S im(S1, S2),并用以下公式表达:

其中Dis(S1,S2)为两个义原在这个层次体系中的路径距离,是一个可以调节的参数。两个义原之间的距离越大,它们的语义相似度越小,两者成反比。

五 聚类处理

给定一个数据样本集 X{X1,X2,…,Xn},根据对象间的相似程度将样本集合分成 k簇:{C1,C2,…,Ck}的过程称为聚类。通常可以分为层次式和非层次式两种[6]。本文采用自底向上的层级聚类方法。该方法的优点是易于理解,实现简便。具体步骤如下:

输入:待聚类的定义集合(n个定义)

1)初始化成 n类使每个类包含一个定义;

2)计算所有 n个类两两之间的相似度;

3)找出相似度最大的两个类合并成一个类,n =n-1;

4)重复步骤 2、3直到最大的相似度小于设定的阈值或最后只有一类时停止。

六 聚类结果分析

术语定义的聚类实验结果使用准确率来进行评价,用公式表示如下:

本文从中国标准化研究院提供的术语数据库语料中随机抽取 1000条术语定义来做实验,聚类结果被分为19类,其中被正确分类的术语定义 778条。实验的聚类正确率为 77.8%。

本文选用知网作为术语定义领域聚类的知识库是因为知网里具有大量区分不同领域的义原。例如:commercial|商、medical|医、computer|电脑、education|教育、weather|天象、politics|政、information|信息、agricultural|农、industrial|工、Animal-Human|动物、animate|生物、chemical|化学物、material|材料、vehicle|交通工具、MusicTool|乐器、machine|机器、music|音乐、sport|体育、law|律法等。这些义原对定义的领域区分与判别起到了很大的支持作用。

实验中我们也发现使用知网进行领域聚类的局限性。由于知网使用的义原的个数为 2200个,但是它所涵盖的词语达 65 000条,概念达80 000多。义原的个数远远小于词语和概念的个数,这样就出现多个概念之间共用同一个义原的情况,影响了领域聚类的准确度。

我们以“phenomena|现象”这个义原为例进行分析,包含该义原的词语有:白色恐怖、雹灾、饱嗝儿、暴洪、悲欢离合、弊病、表面现象、兵荒马乱、病虫害、波谱、擦网球、差错、车流、春寒等。显而易见,在聚类的过程中,这些词语由于共用一个“phenomena|现象”义原,而且该义原在大多数情况下属于第一基本义原,被赋予了一个较高的权重,通过词语的相似度计算,这些词语之间容易获得较大的相似度。由于句子的相似度是建立在词语相似度基础之上,进而又影响到句子的相似度计算,影响了聚类的结果。

同时知网中部分词语的义原描述不够详尽,无法提供对领域聚类的足够支持。例如,飓风只有一个义原描述“wind|风”;泥石流同样只有一个义原描述“stone|土石”。这两个词语属于自然现象,但知网的知识库却不能提供领域聚类的支持。

词条的完备性也会产生一定的影响,由于术语定义中包含的术语较多,有些词语未被知识库所收录,中文是一个开放集合,知网也并不能涵盖所有词语。可见一个知识库的构建是项非常艰巨的工作,同时它的构建总会受一些主观因素的影响。因此,借助知识库进行自然语言处理的相关工作既有可操作性又有其局限性。

七 结束语

术语定义的领域聚类的研究相对来说是一个新课题。定义的自动聚类有助于系统化地研究某个特定领域的术语以及术语定义的词汇、句法,以及语义的内在固有规律。对领域术语库的建设、领域知识的提取与研究具有一定的理论意义和应用价值。将同属于一个领域类别的术语定义划分到一类,不仅可以自动区分开不同领域的同名术语,而且可以集中得到一批同领域的术语定义,对特定领域的术语研究提供了方便。术语定义聚类与通常的文本聚类、句子聚类不同,本文通过考察不同词类对于领域区分程度的差异,作为聚类领域特征的选取准则,将不具有领域区分程度的词类排除在聚类计算过程之外,通过自底而上的层级聚类的方法,有效地解决了术语定义的领域聚类问题。

[1]赵世奇,刘挺,李生.一种基于主题的文本聚类方法[J].中文信息学报,2007(2):58-61.

[2]赵妍妍,秦兵.基于多特征融合的句子相似度计算[G].全国第八届计算语言学联合学术会议 (JSCL-2005). 2005:168-174.

[3]刘群,李素建.基于知网的词汇语义相似度计算 [J]. Computational Linguistics and Chinese Language Processing,2002,7(2):59-76.

[4][EB/OL]http://www.keenage.com.

[5]许石,樊孝忠,张锋.基于知网的语义相关度计算 [J].北京理工大学学报,2005(5):411-414.

[6]姚清耕,刘功申,李翔.基于向量空间模型的文本聚类算法[J].计算机工程,2008(9):39-41.

Cluster Research on Term Definition

ZHANG Rong

D om a in c lus te ring of te rm definition is a re la tive ly new resea rch top ic.In this resea rch,w e took bottom-up hie ra rchica l c lus te ring m e thod for sem antic s im ila rity ca lcula tion based on HowN e t,and se lec ted c lus te r-sp ec ific cha rac te ris tics based on w ords w ith d iffe rent contribution to c lus te ring and s top-used w ords cons truc ting dom a in c lus te r.O ur resultsrea lized the dom a in c lus te r of te rm definition,and achieved a des ired exp e r im enta l result.

te rm,te rm definition,sem antic s im ila rity,dom a in c lus te ring

H083;N04

A

1673-8578(2011)01-0014-05

2010-07-02

九大类试剂的定义(名词解释) 第5篇

1二异丙基胺锂:构造式为(i-C3H7)2N-Li+。英文名称为Lithium diisopropyl amine,缩写为LDA。

2土伦试剂:由氨、硝酸银和氢氧化钠配制的试剂。

3本尼迪特试剂:由柠檬酸、硫酸酮与碳酸钠配制而成的试剂。4抑制剂:能使反应减慢或停止的物质称为抑制剂。

5菲林试剂:是用硫酸铜溶液(费林试剂A)和酒石酸钾钠的氢氧化钠溶液(费林试剂B)混合配制而成的试剂。

6格氏试剂:结构式为RMgX的试剂称为格氏试剂。N−溴代丁二酰亚胺:英文名称为N−bromosuccinimide,缩写为NBS。一种常用的溴化试剂。

8魏悌息试剂:邻位两性离子称为叶立德,由磷形成的叶立德称磷叶立德,磷叶立德是德国化学家魏悌息于1953年发现的,所以也称为魏悌息试剂。

土建工程定义几类工程 第6篇

(一)凡符合下列条件之一者,为 一 类 建筑 工程1.十二层(按能计算建筑面积的)以上的或檐口高度三十六米以上的多层建筑。2.跨度在二十四米以上或檐口高度在十八米以上的单层建筑。3.设有双层吊车或吊车起重能力在五十吨以上工业厂房。4.十层以上的钢及钢筋砼框架结构、剪力墙结构、框架-剪力墙结构及筒体结构 工程。5.高度在五十五米以上,或直径在二十米以上(其他形状单体周长在八十米以上),或池(罐)单体容积在一千五百立方米以上的构筑物。6.球形、椭圆形、双曲线形、圆锥形等复杂形状的钢或钢筋砼结构的构筑物。(不受本条第5款的限制)

(二)凡达不到一 类 工程 标准,符合下列条件之一者 为 二 类 工程1.八层以上至十二层或檐口高度在二十七米以上至三十六米的多层建筑物。2.跨度在十八米以上至二十四米或檐口高度在十二米以上至十八米的单层建筑。3.设有吊车,其起重能力 为 三十吨以上至五十吨的工业厂房。4.六层以上至十层的钢及钢筋砼框架结构、剪力墙结构、框架-剪力墙结构及筒体结构 工程。5.高度在四十五米以上至五十五米,或直径在十二米以上至二十米(其他形状单体周长在四十八米以上至八十米),或池(罐)单体容积在一千立方米以上至一千五百立方米构筑物。6.钢筋砼结构的贮仓、囤仓、江边钢筋砼水泵房。钢及钢筋砼各种形式的支架及栈桥、微波塔。(不受本条第5款的限制)

(三)凡达不到一、二 类 工程 标准,符合下列条件之一者 为 三 类 工程1.六层以上至八层或檐口高度在二十米以上至二十七米的多层建筑物。2.跨度在十二米以上至十八米或檐口高度十米以上至十二米的单层建筑。3.设有吊车,其起重能力 为 三十吨以下的工业厂房。4.二层以上至六层的钢及钢筋砼框架结构、剪力墙结构、框架-剪力墙结构及筒体结构 工程。5.高度在三十米以上至四十五米,或直径在八米以上至十二米(其他形状单体周长在三十二米以上至四十八米),或池(罐)单体容积在五百立方米以上至一千立方米的构筑物。6.带地下室或半地下室的钢筋砼结构的锅炉房、泵房、冷冻房 工程,别墅 工程。高度在八米以上的挡土墙、护坡、独立的钢筋砼设备基础。独立的打桩 工程,如护壁桩、锚杆桩、止水幕桩等。独立的强夯地基 工程。

(四)凡达不到一、二、三 类 工程 标准,符合下列条件之一者 为 四 类 工程1.二层至六层或檐口高度在六米以上至二十米的多层建筑物。2.跨度在六米以上至十二米或檐口高度在六米以上至十米的单层建筑。3.二层的钢及钢筋砼框架结构、剪力墙结构、框架-剪力墙结构及筒体结构 工程。4.除一、二、三 类 工程 以外的钢或钢筋砼、砖石或砖混结构构筑物。5.五米以上至八米的挡土墙、护坡。独立的室外钢筋砼结构的零星 工程(如化粪池)等。室外独立的管径350mm以上排水砼管道的铺设。独立金属结构的围墙或以砼 为 主体的围墙。

VC类定义 第7篇

使用过VB的人一定会对它的对象浏览器有深刻的印象,在VB的对象浏览器中可以方便的查看每个对象的属性、方法和事件,学习起VB对象来非常方便。VC在Windows编程中功能强大,但VC中没有象VB那样的对象浏览器,要了解MFC中各个类的成员时,往往要另外去查一些资料,查看MFC的源文件也很不方便。

我在使用VC的过程中,发现一个快速实现类浏览的方法,使用它不仅可以浏览MFC中的各个类而且可以查看类的各种成员及其源文件。同时,实现起来又非常简单,各位VC的爱好者不妨一试。

首先,在VC中新建一个空的“Win32Application”工程,然后,把MFC的源文件都加入到工程中,即可在VC中实现以上功能。

具体操作过程如下:

运行VC,选择“File”菜单中的“New”;

在出现的对话框中选择“Win32Application”,填上其它信息后,按“OK”;

在出现的对话框中选择“Anemptyproject”,按“Finish”;

在VC的“Project”菜单中选择“AddToProject”子菜单中的“Files”;

在出的文件对话框中,找到以下路径:

“VC安装目录MFCinclude”,把其中所有扩展名为“.h”、“.inl”的文件选中(将文件按类型排序时,选择起来比较容易),按“Ok”;同上,再把“VC安装目录MFCsrc”中的所有扩展名为“.cpp”的文件加入到工程中。(如没有这个目录,请在安装VC时,选择安装源文件)

这时在VC的“Workspace”窗口中,所有的MFC类都会显示出来,你可以尽情

地浏览了!Havefun!!

VC++5的MFC中为程序添加弹出式菜单

姜边・CPCW

弹出式菜单(PopMenu)大家都熟悉,在WIN98的桌面上单击鼠标右键弹出的菜单就是弹出式菜单。通常情况下,弹出式菜单在鼠标右键单击时弹出,当然,也可以根据需要随时弹出。在VC++5的MFC中,管理菜单的类叫CMenu。下面我向大家介绍建立一个弹出式菜单的基本方法。

一、在资源编辑器中建立一个菜单资源

新建一个菜单资源,比如把菜单的ID号为IDC_POPMENU。此菜单有一项两层,即有一个可弹出的菜单项,而此菜单项的弹出内容即为将要建立的弹出式菜单的内容。如右图,“可弹出项”下的菜单即为将要建立的弹出式菜单的内容。实际上,“可弹出项”这个名称在以后的操作中不会被用到,但VC++5不允许直接建立弹出式菜单,所以采用先建立“可弹出项”的方法。

至于每一个菜单项的消息映射,与一般的菜单相同。

二、使用CMenu类对象

CMenu类的成员函数较多,但建立弹出式菜单只需用到其中几个成员函数。

1、LoadMenu函数

原型:BOOLLoadMenu(UINTnIDResource);

其中nIDResource是菜单资源的ID号,这里用的是刚建立的IDC_POPMENU。

2、GetSubMenu函数

原型:CMenu*GetSubMenu(intnPos)const;

此函数用于得到子菜单的指针。nPos为层数,0为第一层子菜单以此类推。

由于我们需要的是“可弹出项”的第一层子菜单,因此用GetSubMenu(0)来得到第一层子菜单的类指针,

3、TrackPopupMenu函数

原型:BOOLTrackPopupMenu(UINTnFlags,intx,inty,CWnd*pWnd,LPCRECTlpRect=NULL);

其中:

nFlags为屏幕坐标属性和鼠标坐标属性

屏幕坐标属性:

TPM_CENTERALIGN横向将菜单以x居中

TPM_LEFTALIGN横向将菜单以x左对齐

TPM_RIGHTALIGN横向将菜单以x右对齐

鼠标按键属性(只在响应WM_CONTEXTMENU消息时有效):

TPM_LEFTBUTTON连续按?右键不会连续弹出菜单,鼠标右键不可用于选定菜单项

TPM_RIGHTBUTTON连续按鼠标右键会连续弹出菜单,鼠标右键可用于选定菜单项

x,y均为屏幕坐标

lpRect菜单所占的区域。如果为NULL,当用户在菜单以外的区域按鼠标键时,菜单会消失

三、实例

1、当鼠标右键单击程序窗口的客户区时,程序会收到一条WM_CONTEXTMENU消息,此时是弹出菜单的最好时机

用ClassWizard中的“AddWindowsMessageHandler”功能添加对WM_CONTEXT消息的响应函数,函数中代码如下:

voidCMyDlg::OnContextMenu(CWnd*pWnd,CPointpoint)

{

CMenumenu;//定义CMenu类对象

menu.LoadMenu(IDC_POPMENU);//装入刚建立的菜单IDC_POPMENUmenu.GetSubMenu(0)->TrackPopupMenu(TPM_LEFTALIGN,point.x,point.y,pWnd);

/*GetSubMenu(0)得到IDC_POPMENU的第一层子菜单,TrackPopupMenu将菜单弹出到(x,y)处。由于设置为TPM_LEFTALIGN,所以菜单以(x,y)为左上角。*/

}

2、在其他时候弹出菜单也可以,比如,可以响应WM_LBUTTONDOWN消息。这样,在鼠标左键单击时也能弹出菜单

用ClassWizard中的“AddWindowsMessageHandler”功能添加对WM_LBUTTONDOWN消息的响应函数,函数中代码如下:

voidCMfc5Dlg::OnLButtonDown(UINTnFlags,CPointpoint)

{

CMenumenu;//定义CMenu类对象menu.LoadMenu(IDC_POPMENU);//装入刚建立的菜单IDC_POPMENUClientToScreen(&point);menu.GetSubMenu(0)->TrackPopupMenu(TPM_LEFTALIGN,point.x,point.y,this);

/*GetSubMenu(0)得到IDC_POPMENU的第一层子菜单,TrackPopupMenu将菜单弹出到(x,y)处。由于设置为TPM_LEFTALIGN,所以菜单以(x,y)为左上角。*/

ScreenToClient(&point);

CDialog::OnLButtonDown(nFlags,point);

}

注意:在WM_LBUTTONDOWN消息中得到的point对象所存的坐标是相对于窗口客户区的,而TrackPopupMenu中的x,y需要是相对于屏幕的,所以需用ClientToScreen函数进行转换,但此消息响应函数要调用CDialog::OnLButtonDown(nFlags,point),故应该用ScreenToClient函数将point所存的坐标还原为相对于窗口客户区的。

VC类定义 第8篇

在用VC开发时常常需要对内存进行操作, 其中C++中提供了运算符new与delete;而C语言库中提供有malloc与free。它们在具体使用时存在着一些差别, 大家也可能有一些疑问;如:为什么C++运算符new在为类对象申请内存时会调用类的构造函数而malloc则不会;为什么用new申请一个对象数组时就必须用delete[]释放而申请一个long类型的数组就能用delete释放, new一个对像与new一个对象数组以及new一个基本数据类型的数组有什么不同;为什么用new申请一个对象用delete[]释放有时会出错, 而有时就成功。文中主要解析VC中为类对象申请内存的过程, 同时解答上述几个疑问, 希望能给大家予以一定帮助。在此说明一下试验的环境:VC6.0编译环境, IDE5.0。

2 malloc与new

这两个操作的区别主要是在申请一个类的对象时, malloc不会调用类对象的构造函数而new会调用, 这里定义一个类用来实际测试, 下面将以这个类为基础讨论malloc与new的差别。

下面看几段代码与它们的执行结果:

代码1:

执行输出:

代码2:

这时没有看到有代码1那样的输出, 可见malloc时并没有去调用类的构造函数, free时也没有调用类的析构函数;这样就验证了new和delete在为类申请内存时会调用类的构造与析构函数, 而malloc和free不会。下面看看它们汇编代码是什么样一个情况。首先来看代码1片段:

其中edx里存放的是CMemoryItem*pItem=new CMemoryItem;这句代码在CPP文件中的行号, offset THIS_FILE (00416690) 则是CPP文件的路径, 8就是这个类的长度, 通过对sizeof (CMemoryItem) 的输出可以证实这类的长度是8, 至于为什么长度会是8, 在这里不做深入的讨论, 接下来就是对new的一个调用。当调用完成后对调用的返回值做一是否为0的验证;紧接着就调用了CMemoryItem类的构造函数, 构造函数会再返回这个对象的起始内存地址。

再来看一下用malloc申请内存的汇编代码, 以加深理解两者的区别。下面的malloc申请内存的汇编代码:

可以看到这里除对堆栈做了两次校验外没有看到任何有关构造和析构函数的调用。从以上分析可以看出两者的区别就在于:用new申请类对象时编译器加入对类构造函数的调用而malloc则没有, 这是因为malloc是C语言中的函数, 在C语言中没有类的概念, 实现时也不会为其加入对构造函数的调用, 如果单步调试到00401D7Ecall operator new (004021c4) 时, 按F11进入它的内部就能看到它的内部仍然是把调用转给了malloc函数, free和delete区别也类似是这样的。

3 new操作的过程

本节来详细看一下申请一个类对象时的构造过程和申请一个类对象数组时的构造过程以及为基本数据类型申请数组时的一些情况, 并对比三者的不同;试验时用的类还是上面的CMemoryItem类。

3.1 new单个类对象的过程

3.1.1 类中有虚函数

通过前面叙述了解new一个类对象过程但并未提及它的构造过程, 这里接着上面的内容解析一下单个类的构造过程。看下面的示例代码:

代码1:

在调用类的构造函数时, 代码段是这样的:

在dword ptr[ebp-28h]中存放着CMemoryItem类对象申请的内存起始地址, 现在跟踪一下类的构造函数来看看内部的执行流程, 看现在的汇编代码:

因为代码较多, 在此只选择其中关键部分的代码来讨论这里把构造函数的整代码分成3部分函数初始化代码、类初始化代码、函数体代码。

(1) 函数初始化代码

首先来简单了解一下00401DF0到00401E1C的这段代码, 主要是一些保存当前状态的操作, 大家可以看到最后一个入栈的寄存器ECX, 那也就是说代码一直执行00401E1C处ECX都是栈顶第一个元素。下面代码接着是00401E1E位置的代码, 它把栈顶的一个元素弹出并保存到了ECX寄存器中, 这个寄存器中当前值是什么呢?可能大家都一直这个疑问, 返回再去看看构造函数调用前的那一句汇编代码:

00401D96 mov ecx, dword ptr[ebp-28h]

这样大家应该明白了, ECX寄存器中存放的就是CMemoryItem对象的起始地址, 这时它被保存入dword ptr[ebp-10h]内存区。

(2) 类初始化代码

这个阶段从00401E1E一直到00401E37, 在这段汇编代码中间没有看到有关在类的构造函数中写的操作。它首先把对象的起始地址存入了dword ptr[ebp-10h], 然后将对象指针偏移4个字节, 因为这个地方存放了类的成员变量m_info;由于它是CString类的对象所以这里调用了它的默认构造函数来构造这个成员变量。接着再看00401E34和00401E37这两句汇编代码;先把对象的起始地址放到EAX寄存器中, 然后把offset CMemoryItem::`vftable' (0041501c) 放入对象前4个字节中, 这里大家肯定有一个疑问那就是这个偏移地址到底是什么?再返回去看CMemoryItem类的声明, 可以看到它的构造函数被声明成了一个虚函数。一些编译器支持虚函数的方法就是为这个类建立一个虚函数表, 可见这个偏移就是这个虚函数表了。

(3) 函数体代码

大家可以看以00401E3D一直到最后的代码就是在构造函数里面对全局变量g_Number加一并输出的过程, 最后构造函数将对象的起始地址放入EAX寄存器中并返回。

3.1.2 形字类中没有虚函数

当申请一个类对象时, 如果这个类中没有虚函数情况则会发现一些变化。还是基于上面的CMemoryItem类, 但是修改一下它的析构函数详细如下:

virtual~CMemoryItem () 这个原来类中析构函数的声明现在把virtual关键字去掉再来跟踪一下程序的执行情况, 下面列出关键部分汇编代码:

上面是程序编译后申请内存部分的汇编代码, 前三句与上面第一节中的汇编代码没有什么不同, 但注意一下第四句, 这句是告诉new函数需要为对象申请内存的长度, 再回顾一下上面汇编代码, 它压栈的是8, 但为什么这里是4呢?

保留这个问题再向下跟踪代码来寻找答案。看看下面这部分代码:

显然这部分代码与上节的代码是没有区别的, 仔细看下面的代码:

这部分汇编代码与上节的相比较看一下有什么不同?和上面的一样, 这部分汇编代码也是函数初始化代码、类初始化代码、函数体代码3部分。首先看一下第一部分显然没有什么不同;接下来看看类初始代码部分开始是对成员变量的构造, 但是少了虚函数表的初始化, 从这里可以发现没有虚函数的类会比有虚函数的类少4个字节, 这也能解释上节的类是8个字节而这里是4个字节了;最后看看剩下的汇编代码也差不多一样。

从这里可以总结出没有虚函数的类会比有虚函数的类少4个字节, 在类的构造代码中也不会有对虚函数表的初始化。这点很重要将影响它们在释放内存时一些流程的不同。下面讲delete操作时再详细讨论。

3.2 new一个类对象数组的过程

上面详细解析了为一个对象申请内存的过程, 再来看一下为一个类申请对象数组时具体发现一些什么情况。还是上面CMemoryItem类, 代码如下:

我们在CMemoryItem*pItem=new CMemoryItem[10];设一个断点看看具体的汇编代码如下:

先分析一下这段代码, 前3句是一样的, 第4句将要申请的内存空间长度入栈;但是申请了10个元素, 每个元素8个字节, 总长80个字节换算成十六进制就是50字节, 但这里入栈时却多了4个字节, 这4个字节是做什么用的呢?再来看一段汇编代码:

这代码段调用new函数之后的代码, 先看00401D5C处的代码eax是new函数返回的内存地址, 它被存入了dword ptr[ebp-1Ch], 记下这个地址后面构造时会用到这个地址。00401D5F00401D6A这段代码是编译器自动插入检查new函数申请内存是否成功的。00401D6C将类的析构函数地址入栈, 00401D71将类的构造函数地址入栈;00401D76这句要注意一下dword ptr[ebp-1Ch] (为类数组申请的内存首地址) MOV给了ECX, 下面边这句把OAH (十进制10) 放到了内存的前4个字节;00401D7F00401D89是分别将数组元素的个数、元素的长度、数组的起始地址 (申请内存块的第5个字节开始) , 00401D8A调用一个函数来构造这个数组, 为了更深入地理解对象数组内存的申请, 进入这个函数看看其中的详细过程, 看下面的汇编代码:

这段代码比以前的代码复杂一些, 同样分段来查看。先看004023C000402400这段函数调用前处理堆栈的这里略过;看0040240B这句, 重点要搞清楚dword ptr[ebp+8]里是什么, 回顾一下刚才入栈的顺序析构函数、构造函数、数组元素的个数、元素的长度、数组的起始地址、EBP (栈基址寄存器) ;按照栈先进后出的原则, 那dword ptr[ebp+8]就是数组的起始地址 (其他参数也按照这个方法计算出来) 。再看这个调用dword ptr[ebp+14h], 按照刚才的算法地址存放着数的构造函数地址, 那么这里与为单个类对象申请内存时构造是一样的。0040241100402417这3句也很清楚, 将数组的起始地址移动了一个元素的长度。0040241A这句调转到004023FA, 而004023FA00402406这几句计算当前元素构造的个数, 从0开始计数, 看到构造组数是从第一个开始一直到最后一个元素。这里分析出当为一个类new数组时, 它实际上多了4个字节 (用来存放数组元素的个数) 。那么如果new不是一个类数组, 一个基本数据类型或者是一个结构体的数组呢?如果new是一个基本数据类型 (long、int等) 的数组, 上面的那种情况是不会出现的 (不会多出4个字节来存放无素的个数) , 而对结构体则分两种情况, 如果结构体中不包函数成员那么和基本数据类型一样, 具体过程大家可以自己测试分析:这里不再赘述。

4 delete[]与delete的差别

上一节对new操作做了详细的讨论, 这一节来讨论一下delete[]与delete的差别;试验时用的类还是上面的CMemoryItem类。

4.1 释放类对象数组时的跟踪

delete[]与delete的差别主要在于前者用来释放new的数组, 后者用来释放new的单个对象, 先把CMemoryItem类的析构函数的virtual修饰符去掉, 然后看看两段代码片段的执行情况。

代码1:

执行输出:

仔细看一下new和delete时数组里元素的构造与析构的顺序是相逆的, 接下来再来看一个示例代码片段的执行:

代码2:

执行输出:

Destructor CMemoryItem Nember[1]

然后出现一个断言失败的对话框, 如图1所示。

单看输出的那一行就可了解大概, 系统把这块内存当一个类来释放, 这样必定会出错。

接下来看一下这个提示框是怎么回事。它提示_CrtIsValidHeapPointer返回失败了, 那这个函数是做什么用的呢?在MDSN中可得到它的解释, 它是用来验证内存指针有效性的一个功能函数。代码就两句, 怎么刚申请的内存再释放就变成无效了呢?来看一下释放的过程吧, 首先看看代码1的汇编实现, 下面是主要的汇编代码版段:

第一句执行后通过ECX中的值探查到ECX存放着pItem指向的地址;紧接着就调用了delete[], 这里列出具体的汇编代码:

在这个调用里循环为了执行每一个数组成员的析构函数, 最后释放整块内存返回。而且大家可以从00402161这句看出, 系统把pItem指向的地址向前移了4个字节, 上节的讨论中知道, 为对象申请数组时会多申请4个字节并把前4个字节存放入数组的元素个数, 那么释放这个数组也得从它的开始位置释放, 所以要向前移动4个字节。这是一个正常的情况, 那么出错的情况是怎么发生的呢?接下来看一下代码2的汇编实现:

第一句不变, 第二句变化了那相关流程会是什么样呢?进入它的内部去跟踪一下。看下面跟踪的汇编代码:

顺着看下来一直到004021C9, 这句过后可得出ECX里存放的是pItem指向的地址。紧接着一直到004021D0, 它是对类析构函数的调用。再向下看程序只做了一些检查就直接调用了释放内存的调用, 这也能解释为什么能看到那一句输出。再想想上面一起讨论了new的过程, pItem指向的地址向前4个字节才是new所得内存的开始, 但看004021E2这句它直接把pItem指向的地址传给了释放内存的调用, 这当参数当然不是一个有效的内存块的起始地址了。如果深入跟踪的话可以了解到在debug版本在堆内存的管理中, 为每一块申请的内存建立了一个链表项并存放在一个链表中, 释放时就去链表里找。而传入的那个地址显然不是一个已申请内存块的正确地址, 所以系统会报错。

在上面实验的类中把CMemoryItem析构函数的virtual修饰符去掉, 现在再把它加做上面的实验看一下情况会有变化吗?在析构函数中加不加virtual修饰符真的在释放时没有差别吗?那么再看一下单个对象的释放。

4.2 释放类对象时的跟踪

同样先把CMemoryItem类的析构函数的virtual修饰符去掉, 然后来看两段代码片段的具体执行情况。

代码1:

执行正常, 再看下面的代码。

代码2:

弹出了上面贴出的那个出错框。大家可能觉得这很正常, 那来看看一段不正常的。现在再把类析构函数的virtual修饰符加在上面的实验看一下情况。代码1没错 (肯定的) , 再执行代码2也没错。是不是有些奇怪了, 为了了解其中原因就看它的汇编代码。下面列出代码:

EDX和ECX存放是的pItem指向的地址, 因为这个类的析构函数加了virtual修饰符, 那么这个类的前4个字节就是析构函数的指针。00401E91这句也就调用了类的析构函数, 这自然不会错。那么为什么类的析构函数不加virtual修饰符时就会出错呢?下面也列出一段汇编代码大家便可明白。

类的析构函数不加virtual修饰符时, delete[]pItem;系统把它当成一个对象数组去释放自然会出错。这不是说只要为类的析构函数加了virtual修饰符就可以不分数组还是单个对象都用delete[]释放了。因为不同编译器或相同编译器的不同版会有不同的编译方法, 只是对VC6.0编译后的程序做了剖析。

5 结语

VC类定义范文

VC类定义范文(精选8篇)VC类定义 第1篇VC++怎样定义类对象如果你定义了一个类(假设是A)那么声明一个A的对象的方法就是:A a;// a 就...
点击下载文档文档内容为doc格式

声明:除非特别标注,否则均为本站原创文章,转载时请以链接形式注明文章出处。如若本站内容侵犯了原著者的合法权益,可联系本站删除。

确认删除?
回到顶部