首页 Visual C++ 6.0开发指南第1章

Visual C++ 6.0开发指南第1章

举报
开通vip

Visual C++ 6.0开发指南第1章 第 1 章 Visual C++与面向对象技术概述 3 第 1章 Visual C++与面向对象技术概述 Windows 编程采用的是面向对象的方法(Objec Oriented Programming,简称 OOP),要编 写真正的 Windows 应用程序,就必须对 OOP 有一定了解。而 Visual C++是 Windows 环境下最 主要的 C++开发环境,它支持面向对象编程,并提供可视化编程环境。 1.1 面向对象技术 面向对象技术不只是一种程序设计的方法,而是建立客观事务...

Visual C++ 6.0开发指南第1章
第 1 章 Visual C++与面向对象技术概述 3 第 1章 Visual C++与面向对象技术概述 Windows 编程采用的是面向对象的方法(Objec Oriented Programming,简称 OOP),要编 写真正的 Windows 应用程序,就必须对 OOP 有一定了解。而 Visual C++是 Windows 环境下最 主要的 C++开发环境,它支持面向对象编程,并提供可视化编程环境。 1.1 面向对象技术 面向对象技术不只是一种程序 设计 领导形象设计圆作业设计ao工艺污水处理厂设计附属工程施工组织设计清扫机器人结构设计 的方法,而是建立客观事务模型,分析复杂事务的思想 方法。面向对象方法的本质,就是强调从客观世界中固有的事物出发来构造系统,用人类常用 的思维方式来认识、理解和描述客观事物。 1.1.1 面向对象的基本概念 要理解面向对象技术,必须了解 3 个概念,即对象(object)、类(class)和面向对象 (object-oriented)。 1.对象 对象是客观世界中的实体或者概念,可以将对象理解为事物。对象可以是系统中任何被 观察到的实体,在构造应用系统的过程中,程序员分析问题,并 对解决该问题所需的组件形成一个观察模型,即产生一个抽象的 对象表示。 对象具有静态和动态的特征,面向对象技术是将静态特征映射 为对象的属性、动态特征映射为对象的方法。图 1.1 所示为一个复 数对象的模型。 在建立客观事务的软件模型时,可以将对象的属性抽象为变量, 将对象方法抽象为函数。 2.类 类是一个抽象的概念,用于描述某一类对象所共有的、本质的属性和类行为。对程序开发 而言,类是数据结构和函数的结合体,是结构体的扩展。“类”这一概念十分有利于全面地分析 客观事务,建立客观事务的模型。 现实世界中的实体可以抽象出类别的概念。对应于计算机世界就有一个类(class)的概念, 实 部 虚 部 加 法 减 法 乘 法 求 模 对象属性 对象方法 复 数 对 象 模 型 图 1.1 复数对象的模型 Visual C++ 6.0 开发指南 4 因为类是一个抽象的概念的对应体,所以计算机不给它分配内存,只给对象分配内存。计算机 世界与现实世界之间的对应关系如图 1.2 所示。 对象 类 计算机 世 界 实体 抽象 类别 现实世界 客观世界 抽 象 抽 象 实 例 化 映 射 主观世界 图 1.2 对象、实体与类的关系 类和对象的关系,就如同整数与 1、2、3 的关系一样,即对象是类的实例化。可以理解 为类是一个抽象的框架,类中变量赋了值就是对象。同样是复数,其类和对象可表示为表 1-1 所示。 表 1-1 复数的类与对象 类 对 象 名称 复数 复数 c1=(5+2i) 属性 具有实部和虚部 实部 a=5 虚部 b=2 行为 能进行复数允许的运算 c1+c2,c1-c2,…… 3.面向对象与面向过程 传统的编程方法被称作面向过程编程。在 C 语言中利用面向过程的编程,是将一个问题看 作一系列要完成的事情。这种面向过程的程序设计方法,不能反映人们解决问题的思路。其设 计方法自顶向下、功能分解;其开发过程是从“做什么”到“如何做”。这种方法存在固有的缺 陷,主要表现为程序的可重用性差、程序维护的一致性差。 面向对象的程序是由若干“对象”有机结合而成。这些对象可以互相通信、协调、配合, 从而共同完成整个程序的任务和功能。换句话说,面向过程的编程方法中,程序是由数据和函 数组成的,而面向对象编程中,程序是由对象组成的。 在描述一个事物时,其属性和行为往往是不能分割的。事物的属性有时会影响事物的行为, 而事物的行为也会改变事物的属性。对象特有的变量和对象的功能函数也是密不可分的,在对 象内部的运行机制中,它们往往是有机地结合在一起。 在面向过程的程序设计中,并不支持变量和函数的结合。而面向对象的程序设计中, 由于有了类的概念,使得程序设计更易实现。面向对象与面向过程程序设计的区别如表 1-2 所示。 第 1 章 Visual C++与面向对象技术概述 5 表 1-2 面向对象与面向过程程序设计 面 向 过 程 面 向 对 象 以功能为中心 以数据为中心 按照预定的顺序执行 事件驱动 功能不稳定 数据具有稳定性 面向对象程序设计方法的核心可表示如下。 □ 设计思路:对客观事物的抽象。 □ 程序特点:对类(对象的存在形式)进行结构化程序设计。 □ 类提供简单的对外接口。 1.1.2 面向对象技术的基本特征 到目前为止,对面向对象的概念的定义仍有不同的认识,但它的继承性、封装性、多态性 等特征基本上得到认可。 1.继承性 真实的对象不是孤立存在的,每个对象都与其他一个或多个对象相关。事实上,当描述一 个新对象时,往往要指出该新对象的特征与已存在的对象的特征有何不同。对于面向对象来说, 继承性是指一个新类可以从现有的类中派生出来,新类具有父类中的所有特性,直接继承父类 的方法和数据,新类的对象可以调用该类及父类的成员变量和成员函数。 继承分单一继承和多重继承。所谓多重继承是指一个类可以从一个以上的类中派生出来。 例如某公司的某职员既是工程师,又是管理人员,则他应同时具有技术人员和管理人员的特征。 很多面向对象的语言都不支持多重继承,但 C++支持。 2.封装性 封装是指把数据和方法放在同一个对象中,对数据的存取只能通过该对象本身的方法来进 行。封装性的实质就是将类包装起来,将要保护的变量和函数用私有成员描述,可供外界调用 的部分用公有成员描述。 3.多态性 多态性是指同一消息被不同的对象接收时,可以解释为不同意义的能力,也就是说,同样 的消息被不同类的对象接收时,会产生完全不同的行为。利用多态性,可以发送一般的消息, 而把所有实现的细节留给接收消息的对象去解决。 说明:操作符的重载也具有多态性。 1.1.3 面向对象设计语言与 Visual C++ 1.面向对象设计语言 面向对象设计语言的产生及发展如下。 Visual C++ 6.0 开发指南 6 □ 20 世纪 60 年代,Simula 语言就具有了类和对象的概念。 □ 70 年代初,美国 Xerox Palo Alto 研究中心推出了 Smalltalk,它完整地体现并进一步丰 富了面向对象的概念。 □ 混合型面向对象程序设计语言出现,如 C++、C#,这类语言一般是在其他语言的基础上 开发出来的。 □ 纯面向对象程序设计语言出现,如 Java 语言。 其中,C++语言是在 C 语言基础上扩充的,是 C 语言的超集,它是支持 OOP 的最主要代 表语言。 2.Visual C++简史 Visual C++的根源不是开始于 Microsoft 公司,而是 Borland 公司。Visual C++的发展过程可 简单表示如下。 □ MS C/C++ 7.0:首次把编译器指明为 C/C++,包含了 MFC 1.0(Microsoft Foundation Class),使 C++语言成为最成功的 OOP 语言,大大促进了 OOP 的软件开发。 □ MS C/C++ 8.0 (Visual C++ 1.0):提供了 Windows 风格的编辑器和调试器,含有 MFC 2.0,与 MFC 1.0 相比,增加了动态链接库 DLL 支持和 OLE(Object Linking and Embedding)。 □ Visual C++ 1.5:增强对 16 位编程支持。 □ Visual C++ 2.0:将资源集成到开发工作台(WorkBench)中,使界面更好,且支持 Windows 3.1、Windows NT3.5、Windows 95。 □ Visual C++ 4.0:支持多重平台和平台间的开发,简化了在多重平台间的移植。 □ Visual C++ 5.0:增加了许多重要功能,如 Active X 编程、Internet 编程等。 □ Visual C++ 6.0:功能更强,MFC 类库更丰富。对数据库支持的增强,包括 ADO(ActiveX Data Object)、OLE Database 的数据控件等。 □ Visual C++ .NET:包括 Visual C++ .NET 2002、Visual C++ .NET 2003、Visual C++ .NET 2005 等几个版本,为面向 Windows 和.NET Framework 的开发人员提供了更多的功能。 在所有领域(包括语言、编译器和核心库)都进行了关键改进。这些改进使 C++开发 人员能够更有效地使用 CLR(公共语言运行时),优化代码的性能,提高应用程序的安 全性。 对于纯粹的基于 Windwos 操作系统的应用程序开发,Visual C++ 6.0 版本仍然是 C++面向 对象编程的最佳选择。 3.为什么要学习和使用 Visual C++ 最近有许多专业的程序员放弃了 Visual C++,而改用了其他产品提供的 RAD(快速应用开 发)环境。许多人认为 Visual C++太古老、太繁琐、学起来太困难了。Visual C++的学习周期确 实比其他语言要长,然而,Visual C++具备很多优点,如下。 □ 灵活性:使用 Visual C++,程序员可以彻底地控制整个开发环境。其他语言则更多地趋 向于保护程序员,而这种保护作用有时会成为开发工作的障碍。 第 1 章 Visual C++与面向对象技术概述 7 □ 能够创建短小高效的程序:Visual C++程序可以开发出运行速度很快的程序,并且避免 了汇编语言存在的各种问题。 □ 应用范围广:C++是编写诸如操作系统、设备驱动程序以及动态链接库(DLL)的强大 语言,这 3 种领域代码的开发依然是 Visual C++的主战场。 说明:VB的数据库支持功能较强,而 Visual C++的图形功能较强。Visual C++是真正的面 向对象编程。 1.2 C++的面向对象特性 作为支持 OOP 的最主要代表语言,C++语言具有面向对象技术的所有特性,并以类和对象 为基础,支持类的继承、封装和多态特性。 1.2.1 C++中的类与对象 C++中的类是用户定义的一种数据类型,是在 Struct 类型基础上的扩展。Struct 类型只是声 明了一些数据,而类不仅包含通常的数据,还包括对数据的操作。C++称类的属性为数据成员, 称类的操作(方法)为成员函数。类封装了数据成员和成员函数。 对象是声明属于某一特定类的变量,也称为类的实例。类的所有对象具有相同的属性和操 作(方法)。 1.C++中类的声明与实现 在 C++中,声明类的一般形式如下。 class 类名 { private: 私有数据和函数 public: 公有数据和函数 protected: 保护数据和函数 }; □ 类声明以关键字 class 开始,其后跟类名。 □ 类所声明的内容用花括号括起来,右花括号后的分号作为类声明语句的结束标志。花 括号“{}”之间的内容称为类体。 □ 类中定义的数据和函数称为这个类的成员(数据成员和成员函数)。 □ 类成员均具有一个属性,叫做访问权限,通过它前面的关键字来定义。顾名思义,关 键字 private 、public 和 protected 以后的成员的访问权限分别是私有、公有和保护的, 把这些成员分别叫做私有成员、公有成员和保护成员。 private 部分的数据成员或成员函数,在类之外是不能访问的,只有类中的成员函数才能访 Visual C++ 6.0 开发指南 8 问。public 部分的数据成员和成员函数可被程序中的任何函数或语句存取。protected 部分说明 的成员或成员函数在类之外是不能存取的,只有类的成员函数及其子类可以存取。 说明:如果没有使用关键字,则所有成员默认声明为 private 权限。在实际编程中,public 成员多为成员函数,用于提供与外界的接口,只有通过这个接口才能实现对 private成员的存取。 如,一个简单的类的声明如下。 class Person {private: char Name[20]; int Age; char Sex; public: void Register(char *name, int age, char sex); void ShowMe(); }; 该例中声明了 Person 类,定义了 3 个私有数据成员,它们只能通过 Register 函数存取。上 面的例子中仅给出了成员函数 Register 的函数原型,而没有定义函数。对于使用者,通常只需 要了解函数原型中给出的函数名、返回类型、参数个数和参数类型即可。成员函数的具体实现 可以放在类声明之外定义,在定义成员函数时,必须在函数名前面加上类名,并用作用分隔符 “::”分隔,以便让编译程序知道该函数属于哪一类。例如: vid Person:: Register(char *name, int age, char sex) { strcpy(Name, name); Age = age; Sex = (sex == 'm'? 'm':'f'); } 2.C++中类的对象的声明与使用 声明了一个类,即定义了一个用户数据类型。为了使用类,还必须说明类的变量,即类的 实例(instance)或对象(object)。声明对象的语法类似于声明变量,如: Person Theperson; 也可以声明由多个对象组成的数组: Person person _array[10]; 还有一种方法是在声明类的同时声明对象,如: class Exampleclass { int y; public: int x; 第 1 章 Visual C++与面向对象技术概述 9 void show(); }myclass; 这样就说明了 myclass 是 Exampleclass 类的一个对象。声明了类的对象之后,就可以对该 类的数据成员和成员函数进行访问。 注意:类中的成员是不能直接访问的,必须通过该类的对象来访问。 类成员的访问方法是:在对象和 public 数据成员或成员函数之间加上“.”。如: myclass.x; myclass.show(); 不能直接访问类的私有成员,如 myclass.y 是错误的。 还可以通过说明对象指针,并通过指针调用类的成员,如: Exampleclass * classPointer=& myclass; classPointer ->show(); 通过 classPointer 指针调用成员函数 show()。 1.2.2 C++类的继承与派生 从一个或多个以前定义的类(基类)产生新类的过程称为派生,这个新类又称为派 生类。类的继承(inheritance)是指新类从基类那里得到基类的特征,也就是继承基类的 数据和函数。而派生的新类同时也可以增加或重新定义数据和操作,这就产生了类的层 次性。 当从现存类中派生出新类时,可以对派生类增加新的数据成员、增加新的成员函数、重新 定义已有的成员函数、改变现有成员的属性。 1.单一继承与多重继承 如果一个派生类可以同时有多个基类,则称为多重继承(multiple-inheritance),这时的派 生类同时得到了多个已有类的特征。如果一个派生类只有一个直接基类则称为单一继承 (single-inheritance)。单一继承和多重继承类的层次关系如图 1.3 所示。 基 类1 基 类2 基 类n 派生类1 派生类2 …… 多重继承 基 类 派生类1 派生类2 单继承 图 1.3 单一继承和多重继承 可见,一个基类可以直接派生出多个派生类。而派生出来的新类同样可以作为基类再继续 派生出更新的类,依此类推形成一个层次结构。 Visual C++ 6.0 开发指南 10 2.派生类的定义 格式 pdf格式笔记格式下载页码格式下载公文格式下载简报格式下载 派生类的格式定义可简单表示如下。 class 派生类名:访问权限 基类名 1,访问限定符 基类名 2,……,访问限定符 基类名 n { private: 成员表 1; //派生类增加或替代的私有成员 public: 成员表 2; //派生类增加或替代的公有成员 protected: 成员表 3; //派生类增加或替代的保护成员 };//分号不可少 其中基类 1、基类 2、……,是已声明的类。可以使用的访问限定符包括 public、private 和 protected。在派生类定义的类体中给出的成员称为派生类成员,它们是新增加的数据和函数成 员。这些新增加的成员是派生类对基类的发展,它们给派生类添加了不同于基类的新的属性和 功能。派生类成员包括新添加的,也包括通过屏蔽作用取代基类成员的更新成员。类的派生过 程可表示为图 1.4 所示。 吸收基类的成员 不论是数据成员,还是函数成 员,除构造函数与析构函数外 全盘接收 改造基类成员 声明一个和某基类成员同名的 新成员,派生类中的新成员就 屏蔽了基类同名成员,称为同 名覆盖(override) 发展新成员 派生类新成员必须与基类成员 不同名,它的加入保证派生类 在功能上有所发展。 重写构造函数与析构函数 图 1.4 类的派生过程 3.派生类的继承方式 派生类对基类的访问控制也是 3 种:公有(public)方式、保护(protected)方式和私有(private) 方式,称为公有继承、保护继承和私有继承。在派生类的定义中,基类前所加的访问限定符有 两方面含义。 □ 派生类成员(新增成员)函数对基类(继承来的)成员的访问(调用和操作)。 □ 从派生类对象之外,对派生类对象中的基类成员的访问。 各继承方式的访问权限如表 1-3 所示。 第 1 章 Visual C++与面向对象技术概述 11 表 1-3 各继承方式的访问权限 基类成员访问权 继 承 方 式 派生类中对基类成员的访问权 外部函数的访问权 public public 可以直接访问 protected protected 不可直接访问 public private private 不可直接访问 public protected 不可直接访问 protected protected 不可直接访问 protected private private 不可直接访问 public 不可访问 不可直接访问 protected 不可访问 不可直接访问 private private 不可访问 不可直接访问 4.派生类的构造函数与析构函数 派生类构造函数的一般形式如下: 派生类名::派生类名(参数总表):基类名 1(参数表 1),…,基类名 n(参数表 n), 内嵌对象名 1(对象参数表 1),…,内嵌对象名 m(对象参数表 m) { 派生类新增加成员的初始化; } 派生类构造函数的执行次序如下。 □ 首先,调用基类构造函数,调用顺序按照它们被继承时声明的基类名顺序执行。 □ 其次,调用内嵌对象构造函数,调用次序按各个对象在派生类内声明的顺序。 □ 最后,执行派生类构造函数体中的内容。 派生类与基类的析构函数没有什么联系,彼此独立,派生类或基类的析构函数只作各自类 对象消亡前的善后工作。派生类析构函数的执行过程与构造函数执行过程相反,执行顺序如下。 □ 首先执行派生类析构函数。 □ 然后执行内嵌对象的析构函数。 □ 最后执行基类析构函数。 1.2.3 类的继承实例 为了使读者对继承的概念有直观地认识,下面给出一个多重继承的实例。已知时间类 TimeType 和日期类 DateType 通过多重继承定义日期时间类 DateTimeType。其中时间类 TimeType 的定义如下。 class TimeType { int hour,minute,second; //时、分、秒 public: Visual C++ 6.0 开发指南 12 TimeType(int h=0,int m=0,int s=0) //构造函数 { hour=h; minute=m; second=s; } void display() //输出时间 { cout< using namespace std; int main() { DateTimeType dt(1,1,2007,11,12,12); //直接使用 DateTimeType构造函数设置日期时间 cout<<"DateTimeType类设定的日期、时间为:"< 标准 excel标准偏差excel标准偏差函数exl标准差函数国标检验抽样标准表免费下载红头文件格式标准下载 成员函数。还有一个虚函数 show_area(),用于计算显示图形的面积。 因为计算三角形、矩形和圆形 3 个类对象的面积的方法是不同的,需重新定义。Figure 类的实 现如下: class figure //基类 { protected: double x,y; //成员变量 public: void set_dim(double i,double j=0) //设置图形参数 { x=i; y=j; } virtual void show_area() //虚函数计算面积 { cout<<"No area computation defined for this class.\n"; } }; 三角形、矩形和圆形 3 个类分别需要覆盖虚函数 show_area,代码如下: class triangle:public figure //三角形类 { public: void show_area() //覆盖虚函数 { cout<<"三角形的高:"<set_dim(10.0,5.0); //设置三角形的参数 p->show_area(); //计算三角形的面积 p=&s; p->set_dim(10.0,5.0); //设置矩形的参数 p->show_area(); //计算矩形的面积 p=&c; p->set_dim(10.0); //设置圆形的参数 p->show_area(); //计算圆形的面积 return 0; } 运行结果如图 1.6 所示,有关本程序的源程序可参见所附光盘。 图 1.6 程序运行结果 在本例中,同样是通过 figure 类指针,调用 show_area()函数,但由于指针对象的不同,实 现的虚函数 show_area 的形式也就不同。程序对虚函数的调用过程可表示为图 1.7 所示。 一般而言,可将类中具有共性的成员函数声明为虚函数,派生类定义虚函数的时候,必须 保证函数的返回值类型和参数与基类中的声明完全一致。 注意:只能通过对象指针或引用来调用虚函数才能实现程序运行时的多态,不能定义虚构 造函数,但可以定义虚析构函数。 第 1 章 Visual C++与面向对象技术概述 17 消息 对象 行为 p->show_area() triangle t show_area() square s show_area() circle c show_area() 计算并显示三角形的面积 计算并显示矩形的面积 计算并显示圆的面积 图 1.7 虚函数调用过程 1.2.6 动态联编与虚函数表 所谓联编是指:计算机程序自身彼此关联的过程,是把一个标识符名和一个存储地址联系 在一起的过程,也就是把一条消息和一个对象的操作相结合的过程。C++中,应用程序的联编 有两种形式:静态联编和动态联编。 □ 静态联编:如果使用对象名和成员选择运算符“.”引用特定的一个对象来调用虚函数, 则被调用的虚函数是在编译时确定的,这时称为静态联编。 □ 动态联编:如果使用基类指针或引用指明派生类对象,并使用该指针调用虚函数(成员选择 符用箭头号“→”),则程序动态地(运行时)选择该派生类的虚函数,称为动态联编。 在面向过程程序设计中,所有程序都采用静态联编来实现。静态联编的特点是函数调用速 度快、效率较高,但是编程灵活性不够。动态联编虽然效率较静态联编低,但是能实现更灵活、 更易维护、逻辑关系更清晰的代码。 C++编译器在编译含有一个或几个虚函数的类及其派生类时,对该类建立虚函数表(Virtual function table,vtable)。虚函数表放置虚函数的地址,使执行程序正确选择每次执行时应使用的 虚函数。 在每个包含虚函数的类中,编译器秘密地放置了一个称之为 vpointer(缩写为 VPTR)的指 针,指向这个对象的 VTABLE。所以无论这个对象包含一个或是多少虚函数,编译器都只放置 一个 VPTR 即可。 VPTR 由编译器在构造函数中秘密插入的代码来完成初始化,指向相应的 VTABLE,这样 对象就“知道”自己是什么类型了。VPTR 都在对象的相同位置,常常是对象的开头。这样, 编译器可以容易地找到对象的 VTABLE 并获取函数体的地址。每当创建一个包含虚函数的类或 从包含虚函数的类派生一个类时,编译器就为这个类创建一个惟一的 VTABLE。 假如在派生类中没有对在基类中的某个虚函数进行重写(overriding),那么还使用基类的 这个虚函数的地址,如一个基类 BASE,有两个虚函数 func1 和 func2,它有两个派生类 A 和 B, 均对虚函数 func2 进行了重写,其虚函数表可简单表示为图 1.8 所示。 说明:VPTR指向的 VTABLE其实就是一个函数指针的数组。现在,VPTR正指向它的第 一个元素,那是一个函数指针。如果 VPTR向后偏移一个 Void指针长度的话,那么它应该指向 了 VTABLE中的第二个函数指针了。这看来就像是一个指针连成的链,从当前指针获取它指向 的下一个指针,这样才能“顺藤摸瓜”。 Visual C++ 6.0 开发指南 18 基类对象 base vptr 派生类A对象 a vptr 派生类B对象 b vptr (*vfunc1)() (*vfunc2)() (*vfunc1)() (*vfunc2)() (*vfunc1)() (*vfunc2)() &base::func1 &base::func2 &base::func1 &a::func2 &base::func1 &b::func2 图 1.8 虚函数表示意图 1.3 C++的一些重要要素 Visual C++应用程序开发是以 C++语言为基础的,有关 C++语言的基本知识及基础语法本 书不作详细介绍,本节只是探讨一些在 Visual C++程序开发中,经常用到的也是容易忽视的 C++ 的一些要素。 1.3.1 类的静态成员 类的静态成员是指用关键词 static 定义的类的成员。一旦把类的成员声明为静态,则无论 该类创建了多少个对象,都只是静态成员的一个拷贝,也就是说,静态成员被类的所有对象共 享。因此,静态成员属于类,而不属于类的对象。 1.静态数据成员 静态数据成员要在类的定义中声明,但静态数据成员的初始化要在类外的全局范围内进行, 而不能在类的构造函数中进行。 使用静态数据成员可以节省内存,因为它是所有对象所公有的,因此,对多个对象来说, 静态数据成员只存储一处,供所有对象共用。静态数据成员的值对每个对象都是一样的,但它 的值是可以更新的。只要对静态数据成员的值更新一次,就可以保证所有对象存取更新后的值, 从而提高时间效率。静态数据成员的使用方法和注意事项如下。 □ 静态数据成员在定义或说明时前面加关键字 static,如 public static int count。 □ 静态成员初始化与一般数据成员初始化不同。静态数据成员初始化的格式如下。 <数据类型><类名>::<静态数据成员名>=<值> 注意:初始化在类体外进行,而前面不加 static,以免与一般静态变量或对象相混淆。且初 始化时不加该成员的访问权限控制符 private,public 等,另外,初始化时使用作用域运算符来 标明它所属类,因此,静态数据成员是类的成员,而不是对象的成员。 第 1 章 Visual C++与面向对象技术概述 19 □ 静态数据成员是静态存储的,它是静态生存期,必须对它进行初始化。引用静态数据 成员时,应采用如下格式。 <类名>::<静态成员名> 2.静态成员函数 对于只使用静态数据成员的成员函数,可以将其声明为静态成员函数。静态成员函数的访 问也可以不通过对象,而直接调用。直接调用时,必须指明它所在的类,这样就明确该函数是 静态成员函数,且函数只调用类的静态数据成员,只与类联系,而不属于任何对象。 说明:C++会区分两种类型的成员函数——静态成员函数和非静态成员函数。这两者之间 的一个重大区别是,静态成员函数不接受隐含的 this指针,所以,它无法访问自己类的非静态 成员。有关 this指针可参见 1.3.3节。 声明方法与静态数据成员一样,前面加上关键词 static。如:static int show()。根据类静态 成员的特性,静态成员的使用主要在以下几个方面。 □ 存储链表的第一个或者最后一个成员的内存地址。 □ 用于保存对象的个数。 □ 作为一个标记,标记一些动作是否发生,例如,文件的打开状态、打印机的使用状态等。 1.3.2 const常量 在类中,可以使用 const 关键字定义一个常量。const 数据成员的声明必须包含初值,而且 这个初值必须是常量表达式,const 常量的值在作用域内保持不变,例如: const int maxSize=128; const int intArray[ ]={1, 2, 3, 4, 5, 6}; const 成员仅存在惟一的一份实体,const 成员在编译期间就对表达式进行初始化。const 成 员本质上就是一种只读(read-only)的静态成员的应用,访问时必须使用类的名称,而不能使 用类对象的名称。用关键字 const 修饰一个指针时,根据其位置的不同有不同的含义。例如, 可以声明一个指向常量的指针: const char *ptr = “Point to constant string”; 此时指针 ptr 所指向的对象不能被改变,但 ptr 本身可以被改变。有了以上声明后,下面的 运算是非法的: str2[1]='a'; 也可声明常量指针: char *const qtr = “A constant pointer”; Visual C++ 6.0 开发指南 20 此时该指针不能指向其他对象,因此下面的赋值是非法的: qtr ="Hi, there! "; 修饰符 const 多用于修饰函数的指针或引用参数,以防止在编程中无意识地改变其值。 说明:可以将 const常量理解为 read-only static,即它是一个静态数据成员,但是只读的, 即用户不能改写,其值在定义时就指定。 1.3.3 this指针 对于每一个类的非静态成员函数,都有一个隐含的 this 指针,该指针指向调用该成员函数 的实例对象。当成员函数使用对象中的非静态成员(无论是成员变量还是成员函数),它事实 上是通过 this 指针来调用该成员的。一般情况下,并不需要显式地使用 this 指针。如下面的 类定义。 class MyClass { public: void set_i(int newi) { i=newi; } private: int i; }; 对编译器而言,成员函数 set_i 的定义事实上如下面的代码所示。 void seti(int newi) { this->i=newi; } 在上例中,this 指针不必写成显式的,但是有时必须写成显式的,如在某些类型的链表管 理中,在需要返回当前调用的对象时等。将指向对象自身的指针作为参数,传递给其他函数, 在实际编程中是一个很常用的技巧。 注意:静态成员函数没有 this指针。因为普通成员函数虽然在物理上只有一份拷贝,但在 逻辑上都认为一个对象有一份拷贝,所以有 this指针,而静态成员函数在逻辑上也只有一份拷 贝,不属于具体的对象,当然没有 this指针。 1.3.4 inline内联函数 内联函数用标识符 inline 定义。程序编译时,编译器就对内联函数在其调用处进行替换, 即将内联函数的实际代码插入在调用处,从而消除执行过程中的函数调用开销。例如,求最大 值的内联函数可表示如下: 第 1 章 Visual C++与面向对象技术概述 21 inline int max(int x, int y) { if (x>y) return x; else return y; } 说明:如果在声明类的同时,在类体内给出成员函数的定义,则默认为内联函数。 与非内联函数不同,如果改变一个内联函数,则所有调用它的源文件都要重新编译,使得 函数变成内联函数,不改变其含义,只是影响目标码的速度和长度。因此内联函数通常用于小 而常用的函数,特别是在一个循环中重复调用。 在某种意义上,内联函数类似于用#define 预处理器命令定义的宏,如上面定义的内联函数 与下面的宏实现的功能基本相同: #define MAX((int x, int y)(x>y?x:y) 然而内联函数与宏的处理方法不同。宏替换由预处理程序进行简单的字符串替换,在替 换过程中不进行语法的检查;而内联函数由 C++编译器进行处理,在插入代码之前即进行语 法检查。 注意:如果内联函数由多个源文件引用,则应将该函数的实现代码放在头文件中,而不能 仅仅将该函数的原型声明放入头文件中。 1.3.5 &操作符引用类型 当声明一个变量是另一个变量的别名时,可以使用&操作符。如下面的代码: int Count=0; int &RefCount=Count; RefCount 被声明为 int 类型的引用,并将其初始化为 int 类型变量 Count。这个定义使 RefCount 和 Count 指向同一内存地址,因此两个变量的数值总是相同的。当改变其中一个变量 的值时,会同时改变另一个变量的值。 定义变量为某个变量的引用时,必须用该声明类型的变量将它进行初始化,且不能让一个 引用变量引用不同的变量,也不能用常量值来初始化引用变量,除非声明该变量为 const 性的 引用。 也可以将函数的参数和返回类型声明为引用。如下面的函数: void Func(int &Param); 调用该函数时,必须向函数中传递 int 类型的变量,该变量用于初始化引用参数 Param。在 函数代码中,Param 是函数调用中传递的变量的别名,这样函数内部对参数的修改会反映到函 数外部被引用的变量。 Visual C++ 6.0 开发指南 22 1.3.6 友元 前面介绍过 C++类的封装,一般将类中的数据成员声明为私有成员,而外部则可以通过类 的公有成员函数对私有成员进行访问。但有时类外的一些函数需要直接访问类的数据成员,而 用户又不想改变该数据成员在类中的访问权限,这时,就需要定义友元。 注意:友元本身不是类的成员,不属于任何类。在类的定义中声明友元时,只要在友元的名 称前加上 friend即可。友元虽然不是类的成员,但它是类的朋友,可以直接访问类的所有成员。 1.友元函数 如果友元是普通函数或另一个类的成员函数,称为友元函数。友元函数是在类的外部访问 类的所有成员的普通函数。一个函数可以是多个类的友元函数,只需在各个类中分别声明即可。 将一个函数声明为某类的友元函数的方法是:在类的定义中提供一个以 friend 开头的函数 原型,如下。 friend <返回值类型> <函数名>(<参数表>); 友元函数的定义,可以在类内也可以在类外。类外定义时,与普通成员函数一样,但不要 加上类名(因为不属于该类)。 友元函数不象成员函数那样在调用时使用对象名,因为它不属于任何一个对象,但使用友 元
本文档为【Visual C++ 6.0开发指南第1章】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑, 图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
该文档来自用户分享,如有侵权行为请发邮件ishare@vip.sina.com联系网站客服,我们会及时删除。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。
本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。
网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。
下载需要: 免费 已有0 人下载
最新资料
资料动态
专题动态
is_653306
暂无简介~
格式:pdf
大小:445KB
软件:PDF阅读器
页数:0
分类:互联网
上传时间:2009-12-12
浏览量:31