当前位置:文档之家› C++类的定义及其应用

C++类的定义及其应用

《C++程序设计》——类的定义及使用准备知识:⑴命名空间(namespace)一个软件往往由多个模块组成,其中会包括由不同程序员开发的组件以及类库提供的组件,因此,在对标识符命名时有可能发生冲突。

一个命名空间将不同的标识符集合在一个命名的作用域内,以防止命名冲突。

比如以如下形式声明一个命名空间s:namespace s{class A{ };void fun();}则引用标识符的方式如下:s::A a;s::fun();即在标识符前加命名空间名称及“::”的前缀。

E1_1如果使用声明:using namespace <已命名的命名空间名称>;比如:using namespace s;该命令用来打开命名空间的限制,则该命名空间中所有的标识符在当前作用域中都可以直接使用,不需要任何前缀。

E1_2在C++标准程序库中,使用了命名空间std,所有标识符都声明在命名空间std中。

在使用C++标准程序库中的任何标识符时,可以直接指定标识符所属的命名空间,例如:std::cout,也可以使用using命令来打开命名空间的限制。

C++标准程序库中中的头文件不再有“.h”的扩展名,因此,在程序开始处使用#include<iostream>、#include<cstdio>、#include<cstring>等包含命令时,可以使用using namespace std;命令打开命名空间的限制。

E1_3在Visual C++ 6.0编译环境中要使用一系列的I/O流类,就应该包含头文件iostream。

⑵对象:现实世界中的一切事物都是对象,对象可以是有形的,比如一间房间,一本书籍;也可以是无形的,比如一个计划。

对象可以是一个简单的个体,比如一个学生;也可以是由其它对象组合而成,比如一个公司有多个部门,每个部门又由许多员工组成。

对类似的对象进行抽象,找出共同的属性就可以构成一种类形。

作为面向对象的程序设计语言,C++支持“抽象”。

将抽象后的数据和函数“封《C++程序设计》——类的定义及使用装”在一起,就构成了C++的“类”。

⑶在面向过程的结构化程序设计中,程序的模块是由函数构成的。

函数将逻辑上相关的语句和数据封装,用于完成特定的功能。

在面向对象的程序设计中,程序的模块是由类构成的。

类是对逻辑上相关的函数和数据的封装,是对问题的抽象描述。

即将抽象得到的数据和函数有机的结合成一个整体,形成“类”。

其中的数据和函数都是类的成员。

类实际上相当于一种用户自定义的类型,在定义一个类时要说明其数据和操作内容。

类的特性:封装、继承和多态。

class类名称标识符{成员列表:包括数据成员和成员函数的定义及存取控制类别。

};类成员函数的实现其中:成员列表:数据成员(属性),成员函数(行为方法)。

成员的存取控制类别:private:除了友元函数外,类的外界(对象)不能直接访问该类别成员,只有类定义中的成员函数或数据成员可以访问该类别成员。

在类定义中private:若紧接著类名称,该关键字可以省略。

※很好的体现了类的封装特性。

public:类的外界(对象)可以直接访问该类别成员,并且可以通过该类别成员访问private类别的类成员。

※定义了类的外部接口。

protected:在涉及类继承时使用。

※类成员的存取控制类别定义没有先后顺序。

作用域说明符:::用于说明类成员的归属。

比如:类定义中的成员函数的定义在类定义中完成,而成员函数的实现通常是在类定义外完成的。

所以,要使用作用域说明符来说明成员函数归属于那一个类。

当然,类定义中的成员函数的实现也可以在类定义中完成,但是,这样的函数通常只包含简单的顺序结构的语句(见内联函数)。

《C++程序设计》——类的定义及使用类的使用:定义类的对象(类的对象是类定义的实例)。

类对象的建立(分配存储空间)需要构造,释放内存空间需要析构。

构造函数:在创建对象时,利用特定值将对象初始化为一个特定的状态。

构造函数在对象被创建时被自动调用,没有函数返回值。

在类的public成员中可以定义有多个参数数量及参数类型不同的构造函数,函数名称即为类的名称。

YSC1-1、YSC1-2构造函数执行步骤:⑴按照初始化列表为相应属性赋初值,如果成员为对象,按照给定的初始值执行该对象的构造函数。

⑵执行构造函数的函数体语句。

YSC1-3、YSC1-4※若在类的定义中没有定义构造函数,C++编译器将自动产生缺省的构造函数。

该函数无参,也不做任何实质性的工作。

因为在对象被创建时自动调用构造函数是“例行公事”。

析构函数:用于完成对象生存期结束前的一些清理工作。

函数调用结束,对象在内存中所占内存空间被释放。

析构函数在对象的生存期即将结束时被自动调用,没有参数和函数返回值。

在类的public成员中可以定义一个(只能是一个)析构函数,函数名称为在类的名称前加符号“~”。

YSC1-1、YSC1-2析构函数执行步骤:若程序中有多个类对象存在,对象析构时的顺序与构造的顺序相反。

YSC1-5※若在类的定义中没有定义析构函数,C++编译器将自动产生缺省的析构函数。

该函数无参,也不做任何实质性的工作。

因为在对象被创建时自动调用析构函数同样是“例行公事”。

※构造函数和析构函数无函数返回值,所以,该函数也无须定义函数类型。

※若有动态分配内存的操作,定义构造函数和析构函数是十分必要的还可以根据需要在类定义中定义拷贝构造函数和赋值函数。

拷贝构造函数:特殊的构造函数。

调用拷贝构造函数的情况:⑴当用已经存在(构造完毕)的同类对象(初始值对象)的引用作为参数,初始化构造新建立的对象时将调用拷贝构造函数。

函数是在构造新的对象时被调用执行的。

函数的参数必须是同类对象的引用。

《C++程序设计》——类的定义及使用YSC1-6-1YSC1-6-1程序中A k(h);语句调用A(const A &a){ x=a.x+2; y=a.y+4; }函数的执行。

const表示不能在函数语句中修改参数对象。

⑵如果函数的形参是类的对象,调用函数时,实参给形参参数传递赋值时将调用拷贝构造函数。

YSC1-6-2⑶如果函数的返回值是类的对象,函数执行结束完成返回时将调用拷贝构造函数。

YSC1-6-3YSC1-6-3程序中k对象是函数f()中的局部对象,函数f()执行结束就不存在了。

编译系统会在主调函数的主函数中创建一个“临时无名对象”,该临时对象的生存期只在调用语句的表达式h=f()中。

执行return k;语句时,实际上是调用拷贝构造函数将k的值拷贝到临时对象中。

函数f()执行结束时k对象释放(注意:该对象要析构),但是,临时对象存在于表达式h=f()中。

计算完该表达式后,临时对象的工作也就完成而被释放了(注意:该临时对象要析构)。

⑷如果被拷贝的对象本体与参数对象的实体是一致的,则无须定义拷贝构造函数,利用编译系统生成的缺省函数即可完成拷贝构造(浅拷贝)。

而被拷贝的对象本体与参数对象的实体是不一致的,则必须定义拷贝构造函数(深拷贝)。

YSC1-7YSC1-7程序中类定义中包含指针成员,申请动态内存空间,应在类中定义拷贝构造函数,在拷贝数据时将调用拷贝构造函数。

这样可以避免产生“两次析构”同一数据的错误产生。

※若在类的定义中没有定义拷贝构造函数,C++编译器将自动产生缺省的拷贝构造函数。

该函数的功能是把初始值对象的每个数据成员的值等值赋值给新建立对象的数据成员。

类的组合:类的组合描述的是类定义中嵌有其它类的对象作为成员的情况,这是一种包含和被包含的关系。

当创建类的对象时,如果该类具有内嵌对象成员,则各内嵌对象将首先被自动创建。

因此,在创建对象(组合类的对象)时,既要对本类的基本类型的数据进行初始化,又要对内嵌对象的成员进行初始化。

在创建一个组合类的对象时,不仅其自身的构造函数将被调用,而且,还将调用其内嵌对象的构造函数,构造函数的调用顺序是:⑴按照组合类中内嵌对象的书写顺序调用内嵌对象的构造函数。

⑵执行组合类构造函数的函数体。

如果定义组合类对象时未指定对象的初值,则默认形式(无形参)的构造函《C++程序设计》——类的定义及使用数被调用,此时内嵌对象的默认形式构造函数也被调用。

析构函数的调用执行顺序与构造的调用执行顺序相反。

如果定义组合类时未定义拷贝构造函数,则C++编译器将自动产生缺省的拷贝构造函数,且调用缺省的拷贝构造函数时系统将调用内嵌对象成员的拷贝构造函数。

如果定义组合类时定义拷贝构造函数,则需要为内嵌对象成员的拷贝构造函数传递参数。

YSC1-8赋值函数:用已经存在(构造完毕)的同类对象的引用作为参数,向已经存在(构造完毕)的同类对象做赋值操作时将调用赋值函数。

该函数实际上是对“=”的操作符重载,尤其当类中含有指针成员时,必须对对象的赋值操作定义赋值函数。

YSC1-9、YSC1-10YSC1-9程序中h=g;语句调用A &operator=(const A &a)函数的执行。

const 表示不能在函数语句中修改参数对象。

h对象是调用该函数的对象,g对象是该函数的参数对象。

该函数作为类的成员函数形式定义,必须有一个返回值。

由于,函数定义时将函数定义为对象的引用(&),所以,语句return *this;返回h对象的引用值。

该函数中的this指针是个隐含于每个成员函数中的特殊指针,他指向正在被该函数操作的对象,在YSC1-9程序中为对象h。

YSC1-11YSC1-11程序中的语句if(this==&s) return *this;是在检查是否为自赋值。

语句delete []p;先释放指针变量p原指向的内存单元,然后在后续语句中重新申请分配内存。

※若在类的定义中没有定义赋值函数,C++编译器将自动产生缺省的赋值函数。

该函数的功能是把表达式赋值号右侧对象的每个数据成员的值等值赋值给赋值号左侧对象的数据成员(这样做要慎重!)。

内联函数:类定义中成员函数可以定义成内联函数,方法是在函数定义前加关键字inline。

在普通函数调用时将程序转到被调函数的内存地址中,结束后再返回,这样做存在有时间及空间上的开销。

函数内联是将函数体在编译时来替换调用函数的语句,也就没有“转来转去”的开销了,但是这样做增加了程序目标代码量。

因此,内联函数是为解决函数调《C++程序设计》——类的定义及使用用的效率问题。

在内联函数中不允许包含循环和开关语句,内联函数定义必须出现在第一次被调用之前。

通常内联函数中只包括简单的顺序结构语句。

并且,编译系统将成员函数的实现在类定义中完成的函数也看成是内联函数。

静态数据成员:某一类的所有对象具有相同的属性(属性的数量、名称及数据类型相同),但各个对象的具体属性值各不相同,这样的属性可以称为对象属性(实例属性)。

相关主题