第6章 类和对象
【考点一】 类的定义
1.类的定义类的定义可以分为两部分:说明部分和实现部分。说明部分说明类中包含的数据成员和成员函数,实现部分是对成员函数的定义。类定义的一般格式如下://类的说明部分class<类名>{public:<成员函数或数据成员的说明>//公有成员,外部接口protected:<数据成员或成员函数的说明>//保护成员private:<数据成员或成员函数的说明>//私有成员};//类的实现部分<各个成员函数的实现>
其中,class是声明类的关键字;<类名>是要声明的类的名字,必须符合标识符定义规则;花括号表示类的声明范围,说明该类的成员,其后的分号表示类声明结束。类的成员包括数据成员和成员函数,分别描述类所表达的问题的属性和行为。关键字public、private和protected称为访问权限修饰符,它们限制了类成员的访问控制范围。各个成员函数的实现即可以在类体内定义,也可以在类体外定义。如果一个成员函数在类体内进行了定义,它将不出现在类的实现部分;如果所有的成员函数都在类体内进行了定义,则可以省略类的实现部分。在类体内定义的成员函数都是内联函数。
2.类成员的访问控制类中提供了3种访问控制权限:公有(public)、私有(private)和保护(protected)。其中,公有类型定义了类的外部接口,任何一个外部的访问都必须通过外部接口进行;私有类型的成员只允许本类的成员函数访问,来自类外部的任何访问都是非法的;保护类型介于公有类型和私有类型之间,在继承和派生时可以体现出其特点。
3.类的数据成员类中的数据成员描述类所表达的问题的属性。数据成员在类体中进行定义,其定义方式与一般变量相同,但对数据成员的访问要受到访问权限修饰符的控制。在定义类的数据成员时,要注意以下几个问题。(1)类中的数据成员可以是任意类型,包括整型、浮点型、字符型、数组、指针和引用等,也可以是对象。但是要注意,只有另外一个类的对象,才可以作为该类的成员,即作为该类的成员对象而存在。自身类的对象是不可以作为自身类的成员存在的,但自身类的指针可以。(2)在类体中不允许对所定义的数据成员进行初始化。
4.类的成员函数类的成员函数描述类所表达的问题的行为。类中所有的成员函数都必须在类体内进行说明。但成员函数的定义既可以在类体内给出,也可以在类体外给出。第一种方式是将成员函数直接定义在类的内部。第二种方式是在类声明中给出对成员函数的说明,而在类外部对成员函数进行定义(但成员函数仍然在类范围内)。这种在类外部定义的成员函数的一般格式是:<返回类型><类名>::<成员函数名>(<参数表>){<函数体>}在类体外定义成员函数时,要注意必须在成员函数名前加上类名和作用域运算符(::)。作用域运算符用来标识某个成员属于某个类。作用域运算符的使用格式如下:<类名>::<成员函数名>(<参数表>)或<类名>::<数据成员名>成员函数的两种定义方式之间是有差别的。如果一个成员函数的声明和定义都在类体内,那么这个成员函数就是内联函数。如果一个成员函数的声明在类体内,而定义在类体外,这时对该成员函数的调用是按一般函数进行的。如果要将定义在类体外的成员函数也作为内联函数处理,就必须在成员函数的定义前加上关键字"inline",以此显式地说明该成员函数也是一个内联函数。成员函数除了可以定义为内联函数以外,也可以进行重载,可以对其参数设置默认值。 【考点二】 对象的定义
1.对象的定义对象是类的实例,一个对象必须属于一个已知的类。因此在定义对象之前,必须先定义该对象所属的类。对象的定义格式如下:<类名><对象名>(<参数表>);其中,<类名>是待定义的对象所属的类的名字。<对象名>中可以有一个或多个对象名,多个对象名之间用逗号分隔。<对象名>中,可以是一般的对象名,也可以是指向对象的指针名或引用名,还可以是对象数组名。<参数表>是初始化对象时需要的,建立对象时可以根据给定的参数调用相应的构造函数对对象进行初始化。无参数时表示调用类的缺省构造函数。
2.对象的成员一个对象的成员就是该对象的类所定义的成员,包括数据成员和成员函数。定义了对象后,可以使用" ."运算符和"->"运算符访问对象的成员。其中," ."运算符适用于一般对象和引用对象,而"->"运算符适用于指针对象(即指向对象的指针)。访问对象成员的一般格式如下:<对象名> .<数据成员名>或<对象名>-><数据成员名><对象名> .<成员函数名>(<参数表>)或<对象名>-><成员函数名>(<参数表>) 【考点三】 构造函数和析构函数
1.构造函数和析构函数的定义。构造函数的作用是在对象被创建时利用特定的值构造对象,将对象初始化为一种特定的状态,使该对象具有区别于其他对象的特征。构造函数在对象被创建的时候由系统自动调用。构造函数也是类的成员函数,但它是一种特殊的成员函数,它除了具有一般成员函数的特性之外,还具有一些特殊的性质:(1)构造函数的名字必须与类名相同;(2)构造函数不指定返回类型,它隐含有返回值,由系统内部使用;(3)构造函数可以有一个或多个参数,因此构造函数可以重载;(4)在创建对象时,系统会自动调用构造函数。
2.缺省构造函数和缺省析构函数缺省构造函数就是调用时不必提供参数的构造函数。缺省的构造函数的函数名与类名相同,它的参数表或者为空,或者它的所有参数都具有默认值。前面日期类Date的定义中,构造函数Date(int y=2000);就是缺省构造函数。如果类中定义了一个缺省构造函数,则使用该函数;如果一个类中没有定义任何构造函数,编译器将生成一个不带参数的公有缺省构造函数,它的定义格式如下:<类名>::<类名>(){}每个类都必须有一个析构函数。如果一个类没有声明析构函数,编译器将生成一个公有的析构函数,即缺省析构函数,它的定义格式如下:<类名>::~<类名>(){}
3.拷贝构造函数类中有一种特殊的构造函数叫做拷贝构造函数,它用一个已知的对象初始化一个正在创建的同类对象。拷贝构造函数的一般格式如下:<类名>::<类名>(const<类名>&<引用对象名>){//拷贝构造函数体}拷贝构造函数具有以下特点:(1)也是一种构造函数,因此函数名与类名相同,并且不能指定函数返顺类型。(2)只有一个参数,是对同类的某个对象的引用。(3)每一个类中都必须有一个拷贝构造函数。如果类中没有声明拷贝构造函数,编译器会自动生成一个具有上述形式的公有的拷贝构造函数。
【考点一】 类的定义
1.类的定义类的定义可以分为两部分:说明部分和实现部分。说明部分说明类中包含的数据成员和成员函数,实现部分是对成员函数的定义。类定义的一般格式如下://类的说明部分class<类名>{public:<成员函数或数据成员的说明>//公有成员,外部接口protected:<数据成员或成员函数的说明>//保护成员private:<数据成员或成员函数的说明>//私有成员};//类的实现部分<各个成员函数的实现>
其中,class是声明类的关键字;<类名>是要声明的类的名字,必须符合标识符定义规则;花括号表示类的声明范围,说明该类的成员,其后的分号表示类声明结束。类的成员包括数据成员和成员函数,分别描述类所表达的问题的属性和行为。关键字public、private和protected称为访问权限修饰符,它们限制了类成员的访问控制范围。各个成员函数的实现即可以在类体内定义,也可以在类体外定义。如果一个成员函数在类体内进行了定义,它将不出现在类的实现部分;如果所有的成员函数都在类体内进行了定义,则可以省略类的实现部分。在类体内定义的成员函数都是内联函数。
2.类成员的访问控制类中提供了3种访问控制权限:公有(public)、私有(private)和保护(protected)。其中,公有类型定义了类的外部接口,任何一个外部的访问都必须通过外部接口进行;私有类型的成员只允许本类的成员函数访问,来自类外部的任何访问都是非法的;保护类型介于公有类型和私有类型之间,在继承和派生时可以体现出其特点。
3.类的数据成员类中的数据成员描述类所表达的问题的属性。数据成员在类体中进行定义,其定义方式与一般变量相同,但对数据成员的访问要受到访问权限修饰符的控制。在定义类的数据成员时,要注意以下几个问题。(1)类中的数据成员可以是任意类型,包括整型、浮点型、字符型、数组、指针和引用等,也可以是对象。但是要注意,只有另外一个类的对象,才可以作为该类的成员,即作为该类的成员对象而存在。自身类的对象是不可以作为自身类的成员存在的,但自身类的指针可以。(2)在类体中不允许对所定义的数据成员进行初始化。
4.类的成员函数类的成员函数描述类所表达的问题的行为。类中所有的成员函数都必须在类体内进行说明。但成员函数的定义既可以在类体内给出,也可以在类体外给出。第一种方式是将成员函数直接定义在类的内部。第二种方式是在类声明中给出对成员函数的说明,而在类外部对成员函数进行定义(但成员函数仍然在类范围内)。这种在类外部定义的成员函数的一般格式是:<返回类型><类名>::<成员函数名>(<参数表>){<函数体>}在类体外定义成员函数时,要注意必须在成员函数名前加上类名和作用域运算符(::)。作用域运算符用来标识某个成员属于某个类。作用域运算符的使用格式如下:<类名>::<成员函数名>(<参数表>)或<类名>::<数据成员名>成员函数的两种定义方式之间是有差别的。如果一个成员函数的声明和定义都在类体内,那么这个成员函数就是内联函数。如果一个成员函数的声明在类体内,而定义在类体外,这时对该成员函数的调用是按一般函数进行的。如果要将定义在类体外的成员函数也作为内联函数处理,就必须在成员函数的定义前加上关键字"inline",以此显式地说明该成员函数也是一个内联函数。成员函数除了可以定义为内联函数以外,也可以进行重载,可以对其参数设置默认值。 【考点二】 对象的定义
1.对象的定义对象是类的实例,一个对象必须属于一个已知的类。因此在定义对象之前,必须先定义该对象所属的类。对象的定义格式如下:<类名><对象名>(<参数表>);其中,<类名>是待定义的对象所属的类的名字。<对象名>中可以有一个或多个对象名,多个对象名之间用逗号分隔。<对象名>中,可以是一般的对象名,也可以是指向对象的指针名或引用名,还可以是对象数组名。<参数表>是初始化对象时需要的,建立对象时可以根据给定的参数调用相应的构造函数对对象进行初始化。无参数时表示调用类的缺省构造函数。
2.对象的成员一个对象的成员就是该对象的类所定义的成员,包括数据成员和成员函数。定义了对象后,可以使用" ."运算符和"->"运算符访问对象的成员。其中," ."运算符适用于一般对象和引用对象,而"->"运算符适用于指针对象(即指向对象的指针)。访问对象成员的一般格式如下:<对象名> .<数据成员名>或<对象名>-><数据成员名><对象名> .<成员函数名>(<参数表>)或<对象名>-><成员函数名>(<参数表>) 【考点三】 构造函数和析构函数
1.构造函数和析构函数的定义。构造函数的作用是在对象被创建时利用特定的值构造对象,将对象初始化为一种特定的状态,使该对象具有区别于其他对象的特征。构造函数在对象被创建的时候由系统自动调用。构造函数也是类的成员函数,但它是一种特殊的成员函数,它除了具有一般成员函数的特性之外,还具有一些特殊的性质:(1)构造函数的名字必须与类名相同;(2)构造函数不指定返回类型,它隐含有返回值,由系统内部使用;(3)构造函数可以有一个或多个参数,因此构造函数可以重载;(4)在创建对象时,系统会自动调用构造函数。
2.缺省构造函数和缺省析构函数缺省构造函数就是调用时不必提供参数的构造函数。缺省的构造函数的函数名与类名相同,它的参数表或者为空,或者它的所有参数都具有默认值。前面日期类Date的定义中,构造函数Date(int y=2000);就是缺省构造函数。如果类中定义了一个缺省构造函数,则使用该函数;如果一个类中没有定义任何构造函数,编译器将生成一个不带参数的公有缺省构造函数,它的定义格式如下:<类名>::<类名>(){}每个类都必须有一个析构函数。如果一个类没有声明析构函数,编译器将生成一个公有的析构函数,即缺省析构函数,它的定义格式如下:<类名>::~<类名>(){}
3.拷贝构造函数类中有一种特殊的构造函数叫做拷贝构造函数,它用一个已知的对象初始化一个正在创建的同类对象。拷贝构造函数的一般格式如下:<类名>::<类名>(const<类名>&<引用对象名>){//拷贝构造函数体}拷贝构造函数具有以下特点:(1)也是一种构造函数,因此函数名与类名相同,并且不能指定函数返顺类型。(2)只有一个参数,是对同类的某个对象的引用。(3)每一个类中都必须有一个拷贝构造函数。如果类中没有声明拷贝构造函数,编译器会自动生成一个具有上述形式的公有的拷贝构造函数。