《类与对象的构造设计》由会员分享,可在线阅读,更多相关《类与对象的构造设计(47页珍藏版)》请在金锄头文库上搜索。
1、第6章 类与对象的构造设计n本章的学习目的与人们认识客观世界一样,面向对象技术 认为客观世界是由各种各样的实体组成,每个 实体都可表示成一个对象。因此,客观世界 是由各种各样的对象组成,每种对象都有各 自的内部状态和运动规律,不同对象间相互 作用和联系就构成了各种不同的系统,从而 形成了客观世界。因此,在面向对象的程序 中,客观系统自然被描绘成一系列完全自治 、封装的对象。由此可见,对象是组成面向 对象程序的基本单位。面向对象的程序又将对象划分成类,类定义了属于 该类的所有对象的共同特征,它可作为生成对象的一 种 模板,使对象成为类的实例。从语言角度来说,类是一种新的数据类型,是一 种 用户自
2、定义类型,而对象是具有这种类型的变量。类 是 一种将数据和作用于这些数据上的操作组合在一起的 复 杂数据类型,是可重用的基本单元。总之,类和对象是面向对象程序设计的核心支柱 , 利用它们可以实现数据的抽象、数据和操作的封装以 及 信息的隐蔽,是实现其他许多高级特性的基础。因此 , 我们应该学习类和对象的定义、设计和实现方法。通 过 面向对象程序设计实践进一步学习和领会面向对象的 基 本思想和方法技术。n本章的学习内容学习和掌握类的定义方法和对象的创建方法 。学习和掌握类的成员访问权限控制方法。学习和掌握构造函数与析构函数的用法学习和掌握类的封装、可见性和引用的操作 方法了解结构、联合的面向对象
3、特性和用法。3.1 类的构造和对象的创建3.1.1 类设计的基本原则在面向对象的程序中,客观系统自然被描绘成一系列完全自治、封装的 对象,并将这些对象划分成类,类定义了属于该类的所有对象的共同特征, 它可作为生成对象的一种模板,使对象成为类的实例。从整体功能层面谈类设计,有如下三条原则:单一功能原则(Single Responsibility Principle)一个class就其整体应该只提供单一的服务。如果一个class提供多样 的服务,那么就应该把它拆分,反之,如果一个在概念上单一的功能却由 几个class负责,这几个class应该合并。开放/封闭原则(Open/Close Princi
4、ple)一个设计并实现好的class,应该对扩充开放,而对修改封闭。即,这 个class应该是允许扩充的,但不允许修改。如果需要功能上的扩充,一般 来说应该通过添加新类实现,而不是修改原类的代码。添加新类不单可以 通过直接继承,也可以通过组合。最小惊讶原理(Least Surprise Principle)在重载函数或者用子类实现父类虚函数时,应该基本维持函数原来所期 望的功能。3.1.2 类的说明和对象的定义 类定义的一般格式如下:class class_name private: /私有成员,缺省默认值private variables and function;protected: /保
5、护成员protected variables and function;public: /公有成员public variables and function; object_list; 说明:(1)class_name是类名;(2)关键字public、private和protected是访问 权 限修饰符,表示三种不同的访问权限。(3)类的成员既可包括变量,又可包括函数。 (4) object_list为可选项,用户可在说明类之后 ,根据需要再定义类的对象。例如:class_name object_list;【例3.1】 类的说明与对象定义实例 #include const int SIZE=
6、10; class stack /类名很重要 private: /私有成员部分char stkSIZE;int tos; public: /公有成员部分void init();void push(char ch);char pop(); ; / 初始化成员变量tos void stack : init() tos=0; /把一个字符压入栈中 void stack : push(char ch) if(tos=SIZE)cout const int SIZE=10; class stack /类名很重要 private: /私有成员部分char stkSIZE;int tos; public:
7、/公有成员部分void init() tos=0; /内置定义void push(char ch);char pop();void test() x=pop(); 3.1.4 对类成员的访问 类成员访问的原则是:(1)成员函数可直接访问同类中的成员变量 和调用同类中的成员函数,不用在函数名前 加上对象名。因为公用成员的作用域是不但 包括类说明体,还包括它所属对象的可视范 围(静态成员除外);私有成员或受保护成 员的作用域仅限于类的说明体和类的成员函 数。 (2)可以在类外访问公用成员,但必须在成 员名前加上对象名。int main() stack s1,s2; int i ; /在类外访问公用
8、成员s1.init(); s2.init(); s1.push(a); s2.push(x); s1.push(b); s2.push(y); s1.push(c); s2.push(z); for(i=0;i 上一页|下一页 第4页/共4页所使用的关键键字访问权访问权 限public (公有成员员)可以为类为类 的成员员函数、友元函 数和外部的所有函数所访问访问protected(受保护护成员员)只能为类为类 的成员员函数和 友元函数所访问访问private(私有成员员)只能为类为类 的成员员函数和友元函数所访问访问3.2 构造函数和析构函数 n在OOP中,创建对象时都需要作某种形式的初始化
9、,为此,在 C+的类说明中,引进了构造函数(constructor function), 供创建类的实例对象时调用,并自动完成对象的初始化。例如: class stack char stkSIZE; int tos; public: stack( ); /这是一个构造函数 void push(char ch); char pop( ); ; stack:stack( )cout public:(); / 构造函数(const /拷贝构造 ; :(const public:pointer(int cx,int cy)x=cx; y=cy;pointer(const pointer y=p.y;
10、;void main() pointer ob1(40,50);pointer ob2=ob1;n 浅复制与深复制 (1)浅复制:在用一个对象初始化另一个对象时,如果只复 制了成员,并没有复制资源,使两个对象同时指向了同一 资源的复制方式称为浅复制,如图(a)所示。 (2)深复制:在用一个对象初始化另一个对象时,如果不仅 复制了成员,也复制了资源,则这种复制方式称为深复制, 如图(b)所示。n 如果在类中没有显式定义复制构造函数,则用一个对 象初始化另一个对象时只能用编译器提供的缺省复制 构造函数来进行浅复制;否则可用显式定义的复制构 造函数来进行深复制。(3)如果类中包含指针成员且在创建一个
11、对象时需要动 态分配内存资源,则必须显式定义复制构造函数,以 实现深复制。如果在类中不显式定义复制构造函数, 则用一个对象初始化另一个对象时只能用编译器提供 的缺省复制构造函数来进行浅复制,就会使两个对象 的成员指针指向同一个内存区,当一个指针被释放以 后,另一个指针就会悬空,出现错误。3.2.3 析构函数的特性和用法析构函数也是成员函数,与构造函数相对应 ,命名是在构造类名前加 (波浪线)。 析构函数只能是无返回值类型。 析构函数不能有任何参数。 析构函数不能重载,一个类只允许有一个析 构函数。 当对象离开其有效范围,或被取消时,析 构函数将被调用来释放对象所占用的内存。 因此,析构函数的定
12、义,一般是由一系列的 delete组成。#include class sample private: char *pointer_char; public: sample()pointer_char=NULL; ; sample(sample strcpy(pointer_char,ob.pointer_char); ; sample() if(pointer_char!=NULL) delete pointer_char ; ;3.3 类的静态成员和动态存储分配 n静态成员是类的所有对象共享的成员,而不 是某个对象所特有的成员,是属于整个类的 成员。它是为解决同一个类的不同对象之间 数据和函
13、数的共享而设计的。 n静态成员分为静态数据成员和静态成员函数 。其定义格式为:static ;n静态成员函数是被一个类中所有对象共享的成员 函数,不属于某个特定对象。因此,一般只用于 访问静态数据成员或全局变量。 n调用静态成员函数,可以在其名字前面加类名或 对象名,但使用对象名容易令人产生混淆,故不 鼓励使用。例3.4 静态成员的定义方法 /student.h #include #include class Student protected:static int total;char name11;public:Student(char* pname=“no name”);Student(
14、);static int number() return total; Student:Student(char* pname) cout class MyClass private:static int m_Count;public:static int get_Count() return m_Count; ;static void Add() m_Count+; ; int MyClass:m_Count=0; /必须在类外进行初 void main() cout=new 功能:分配一块与相适应的存储空间 ,若分配成功,将这块内存空间的首地址存 入指针变量,否则置指针变量的值为NULL(
15、 空指针值,即0)。格式2:=new ( ) 功能:分配一块与相适应的存储空间, 并 用为分配好的存储空间置初值。若分配 成 功,将这块内存空间的首地址存入指针变量, 否 则置指针变量的值为NULL(空指针值,即0) 例如:int *p;p=new int(100); /动态存储分配一个整数单元 ,/并给它赋初值100。格式3:=new 功能:申请大小为的数组空间 。 但创建数组时,不能为该数组指定初始值。例如:int *p;p=new int10; /动态分配一个含 /有10个整数的数 组。ndelete运算符的二种常用格式:格式1:delete 功能:释放 指向的动态存储空间 。例如: delete p;格式2:delete 功能:用于释放数组占用的动态存储空间。例如:int *p;p=new int10;delete p;使用的语语法格式使用方法列举举 pointer_var = new var_type ; delete pointer_var ; int *p; p=new int; int *q; q=new int(1999); /初始化 float *f; f=new float15; /为为一维维 数组组分配动态动态