面向对象程序设计 理论篇

36
面面面面面面面面 面面面 武武武武 武武武武武武武武武武 武武武武武武武 -- 武武武武武武武武武武武武武武武 C++ 武武 武 武 武武 武武武武武武武 By: By: 面面 面面 面面 面面 Email: [email protected] Email: [email protected] Room: 7-501 Room: 7-501

Upload: heman

Post on 12-Jan-2016

108 views

Category:

Documents


4 download

DESCRIPTION

武汉大学-资源与环境科学学院-地理信息科学系. 面向对象程序设计 理论篇. By: 任福 博士 Email : renfu @ whu.edu.cn Room : 7-501. 教材及参考资料:. 《 面向对象的理论与 C++ 实践 》 王 燕 编著 清华大学出版社. 第七章:类的定义及其类对象的封装性. C++ 提供了数据结构的封装与抽象,它为程序员提供了定义新的数据类型 ——“ 类 ” 的简单而强大的工具。类本身能够控制外界对它的数据成员的访问从而避免了非授权访问操作。. 第七章:类的定义及其类对象的封装性. 以前,定义结构体类型,描述一个对象 : - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: 面向对象程序设计 理论篇

《面向对象程序设

计》

《面向对象程序设

计》

面向对象程序设计理论篇

武汉大学-资源与环境科学学院-地理信息科学系

教材及参考资料:《面向对象的理论与 C++ 实践》 王 燕 编著 清华大学出版社

By: By: 任福 任福 博士博士

Email: [email protected]: [email protected] Room: 7-501Room: 7-501

Page 2: 面向对象程序设计 理论篇

《面向对象程序设

计》

《面向对象程序设

计》

第七章:类的定义及其类对象的封装性

C++ 提供了数据结构的封装与抽象,它为程序员提供了定义新的数据类型——“类”的简单而强大的工具。类本身能够控制外界对它的数据成员的访问从而避免了非授权访问操作。

Page 3: 面向对象程序设计 理论篇

《面向对象程序设

计》

《面向对象程序设

计》

第七章:类的定义及其类对象的封装性

以前,定义结构体类型,描述一个对象 :struct SPerson // 只有数据成员{

char name[20]; // 姓名char sex; // 性别 int age; // 年龄

};

我们把一个对象可能具有的动作,加入到对象的描述中,就形成了类。

Page 4: 面向对象程序设计 理论篇

《面向对象程序设

计》

《面向对象程序设

计》

◆ 7 . 1 C++ 类的构成

1 、 class 声明 : 〖举例〗 类似于 struct ,但是 class 中除变量的声明外,还含有函数的声明,还具有公有、保护、私有成员(数据或函数)。

2 、成员类型(数据和函数)( 1 )公有成员( public, 不可以省略)( 2 )保护成员( protected, 不可以省略)( 3 )私有成员( private, 放在第一段时,可以省略)

3 、类的构造(建立)( 1 ) class (保留字)声明;( 2 )声明或定义各段内容( public, protected, private ),段内定义的函数为 inline 型;( 3 )语法规则:“ {} ;”;类的继承。

第七章:类的定义及其类对象的封装性

Page 5: 面向对象程序设计 理论篇

《面向对象程序设

计》

《面向对象程序设

计》

◆ 7 . 1 C++ 类的构成

第七章:类的定义及其类对象的封装性

class < 类名 >

{ [ [private:] // 私有成员,缺省存取权限< 数据成员及成员函数 > ]

[ public: // 公有成员< 数据成员及成员函数 > ]

[ protected: // 保护成员< 数据成员及成员函数 > ]

} ;

私有成员:只允许类内成员函数存取它公有成员:允许类内和类外函数存取它保护成员:允许类内和其派生类函数存取它

Page 6: 面向对象程序设计 理论篇

《面向对象程序设

计》

《面向对象程序设

计》

◆ 7 . 2 成员函数的定义1 、在类定义体中声明函数或变量,在别处(实现文件,如*.cpp 等)定义函数;2 、声明函数时,函数的参数可以只指出参数的类型(如 SetPoint ( POINT, int ) ; )3 、声明和定义函数时,函数的返回类型要一致;4 、在类之外定义成员函数时,必须在函数名之前加类名(如, void CGeoPoint::SetPoint(POINT p, int n ) ) ;5 、函数的缺省变量值在声明时给定,而在实现定义时不需给出(如, int SetType(int nType = 1); int CGeoPoint::SetType(int nType/* = 1*/); )6 、内置函数:提高效率

( 1 )隐式定义(函数定义在类定义体内);( 2 )显示定义(函数定义在类定义体外,用冠以关键 字 inline 在函数类型前面);

第七章:类的定义及其类对象的封装性

Page 7: 面向对象程序设计 理论篇

《面向对象程序设

计》

《面向对象程序设

计》

◆ 7 . 3 类与对象1 、类与对象的关系类:把具有同样性质和功能的东西所构成的集合称为类。在 C++ 中,可以把具有相同内部存储结构和相同一组操作的对象看成属于同一类。对象: 在指定一个类后,往往把属于这个类的对象称为类的实例。实际上对象和实例表达的是同一个意思。类与对象的关系: 在 C++ 中可以理解成数据类型和变量的之间的关系,如 double x; CObject obj;

对象的定义(类的实例化):( 1 )在定义类的同时创建对象:(全局对象,容易造成混乱,在生命期内有效) 〖举例〗( 2 )在使用时定义对象

第七章:类的定义及其类对象的封装性

Page 8: 面向对象程序设计 理论篇

《面向对象程序设

计》

《面向对象程序设

计》

◆ 7 . 3 类与对象2 、类的使用类的使用:定义对象,通过类的公有函数或成员变量访问或作用于类。( 1 )类的对象: CGeoMap map

map.SetScale(1000);// 等价于 map.CGeoMap::SetScale(1000);map.m_nScale;

( 2 )类的指针:CGeoMap* pMap = new CGeoMap;// 开辟空间(书中相关内容有误)pMap->SetScale(1000); pMap->m_nScale; delete pMap; // 释放空间

第七章:类的定义及其类对象的封装性

Page 9: 面向对象程序设计 理论篇

《面向对象程序设

计》

《面向对象程序设

计》

◆ 7 . 3 类与对象3 、名字解析map.SetScale(1000); 等价于 map.CGeoMap::SetScale(1000); 所以,在多个类中可以定义相同的成员变量或成员函数而不会出现二义性。如:

CGeoPoint{

public: void Draw(CDC* pDC);

};

CGeoLine{

public: void Draw(CDC* pDC);

};

CGeoPoint point;CGeoLine line;point.Draw(pDC); line.Draw(pDC); // 无二义

第七章:类的定义及其类对象的封装性

Page 10: 面向对象程序设计 理论篇

《面向对象程序设

计》

《面向对象程序设

计》

◆ 7 . 4 构造函数与析构函数 目的:与一般数据类型一样使用,使得建立的对象始终与其定义域相关,并且对对象 进行初始化或对象 占有空间的释放。 构造函数和析构函数除具有普通函数的许多共性外,还具有一些独特的特性,如下:( 1 )无函数返回类型;( 2 )不能被继承;( 3 )构造函数可以有缺省参数;( 4 )析构函数可以是虚的( virtual ),但构造函数不可以;( 5 )不可以取地址; ( 不可以利用函数指针 )( 6 )不能用常规方法调用构造函数;当使用限定名(对象 名)时可以调用析构函数;如, A a; a.~A();( 7 )当定义对象时,编 译程序 自动调用构造函数;当删除对 象时,编 译程序 自动地调用析构函数;

第七章:类的定义及其类对象的封装性

Page 11: 面向对象程序设计 理论篇

《面向对象程序设

计》

《面向对象程序设

计》

◆ 7 . 4 构造函数与析构函数

1 、构造函数

( 1 ) 构造函数的名字必须与类名相同,否则与一般成员函数一样;

( 2 ) 构造函数没有返回值;

( 3 ) 构造函数的目的是对对象 进行初始化;(否则变量随机取值,易造成错误)

( 4 ) 构造函数是在对象 被构造时被自动调用;(对象指针须在分配空间时自动调用构造函数),如, A* p; // 还没有调用构造函数 p = new A;// 调用构造函数

( 5 )构造函数可以调用自定义函数以初始化对象;

第七章:类的定义及其类对象的封装性

Page 12: 面向对象程序设计 理论篇

《面向对象程序设

计》

《面向对象程序设

计》

◆ 7 . 4 构造函数与析构函数

2 、参数化的构造函数

对象的 初始化通过构造函数传递的参量进行的,在构造对象必须给定参数。

第七章:类的定义及其类对象的封装性

Page 13: 面向对象程序设计 理论篇

《面向对象程序设

计》

《面向对象程序设

计》

◆ 7 . 4 构造函数与析构函数

3 、缺省参数的构造函数

缺省参数:单缺省、多缺省(遵循原则:缺省参数必须是参数表中最后的参数(即最右端))

spliteFile(char* szFullName, char* szDir = NULL, char* szName = NULL, char* szTitle = NULL, char* szExt = NULL );

缺省参数并不只用于构造函数,一般的成员函数,甚至于一般的全局函数都可以使用缺省函数。

第七章:类的定义及其类对象的封装性

Page 14: 面向对象程序设计 理论篇

《面向对象程序设

计》

《面向对象程序设

计》

◆ 7 . 4 构造函数与析构函数

4 、多构造函数

构造函数的重载。

一个类可以具有多个构造函数,以适应不同的场合。

多构造函数情况下,当有缺省参数的构造函数时,注意避免发生二义性。

第七章:类的定义及其类对象的封装性

Page 15: 面向对象程序设计 理论篇

《面向对象程序设

计》

《面向对象程序设

计》

◆ 7 . 4 构造函数与析构函数

5 、拷贝构造函数

是特殊的构造函数;将参数代表的对象 逐域拷贝到新创建的对象中。

( 1 )系统产生: A a(10,20); A b(a);

( 2 )用户定义 : A(const A& p ){x=p.x;y=p.y;}

第七章:类的定义及其类对象的封装性

Page 16: 面向对象程序设计 理论篇

《面向对象程序设

计》

《面向对象程序设

计》

◆ 7 . 4 构造函数与析构函数

6 、动态存储

C 中: malloc() 与 free();

C++ 中: new 与 delete;

new 与 malloc 相比好处为:

①new自动计算所分配的类型的大小,既方便,有避免了分配空间的偶然错误;

②自动返回正确的指针类型,不需要指针的类型转换;

③可以用 new将分配的对象 初始化。

第七章:类的定义及其类对象的封装性

Page 17: 面向对象程序设计 理论篇

《面向对象程序设

计》

《面向对象程序设

计》

◆ 7 . 4 构造函数与析构函数

( 1 ) new 的使用

名字指针 = new 名字类型 [初始化值 ] ;如,

CGeoPoint* point = new CGeoPoint;

Int * mm = new int[100];

memset(mm,0x00,sizeof(int)*100);//将空间清空

double* nn = new double[1][2][3];// 数组中的任何一维大小不能缺省

第七章:类的定义及其类对象的封装性

Page 18: 面向对象程序设计 理论篇

《面向对象程序设

计》

《面向对象程序设

计》

◆ 7 . 4 构造函数与析构函数

( 2 ) delete 的使用

delete 名字指针;如,

delete point;

delete[ ] mm;

delete[ ] nn;

备注:删除之前要判断当前指针是否已经为空

第七章:类的定义及其类对象的封装性

Page 19: 面向对象程序设计 理论篇

《面向对象程序设

计》

《面向对象程序设

计》

◆ 7 . 4 构造函数与析构函数 ( 3 ) new 和 delete 的使用

new 和 delete配对使用。如,

①动态分配和释放存储区 (int* p = new int; delete p;)

②动态分配并初始化存储区;

int* p = new int ( 200 ) ; //将 200赋值给 p

delete p; // 要判断是否为空

③动态分配数组 〖举例〗

int* p = new int[50];

delete[ ] p;// 要判断是否为空

④为结构类型的变量分配存储区 〖举例〗

第七章:类的定义及其类对象的封装性

Page 20: 面向对象程序设计 理论篇

《面向对象程序设

计》

《面向对象程序设

计》

◆ 7 . 4 构造函数与析构函数 ⑤为对象 动态分配存储区

CGeoPoint* p = new CGeoPoint(10,20);

If( NULL != p )

{

delete p;

p = NULL;

}

第七章:类的定义及其类对象的封装性

Page 21: 面向对象程序设计 理论篇

《面向对象程序设

计》

《面向对象程序设

计》

◆ 7 . 4 构造函数与析构函数 ⑥为对象数组 动态分配存储区

CGeoPoint* p = new CGeoPoint[10];

If(NULL != p)

{

delete[ ] p;

p = NULL;

}

〖举例〗

第七章:类的定义及其类对象的封装性

Page 22: 面向对象程序设计 理论篇

《面向对象程序设

计》

《面向对象程序设

计》

◆ 7 . 4 构造函数与析构函数 7 、析构函数

是类的成员函数,类名前家“ ~” ,无参数和返回类型,用于空间的释放(如 delete 操作)。

第七章:类的定义及其类对象的封装性

Page 23: 面向对象程序设计 理论篇

《面向对象程序设

计》

《面向对象程序设

计》

◆ 7 . 5 静态成员 1 、定义

在类定义中,其成员(数据成员和函数成员)可以声明成静态的,即用关键字 static ,这些成员被称为静态成员。它的特征是不管这个类创建了多少个对象,而其 静态成员只有一个副本(拷贝),这个副本对该类所有的对象 共享。

第七章:类的定义及其类对象的封装性

Page 24: 面向对象程序设计 理论篇

《面向对象程序设

计》

《面向对象程序设

计》

◆ 7 . 5 静态成员 2 、静态数据成员 〖举例〗

第七章:类的定义及其类对象的封装性

Page 25: 面向对象程序设计 理论篇

《面向对象程序设

计》

《面向对象程序设

计》

◆ 7 . 5 静态成员 3 、静态成员函数

( 1 )成员函数前加 static 关键字;

( 2 )使用时需指出作用(调用)对象,或用“类名::”作为限定词;如 b2.Add(b1) 或 Office::Add(b1);

( 3 )不属于某个特定的对象,而是属于类的;不 像一般的成员函数那样随意地访问对象中的非 静态的数据内容。

( 4 )函数内容(数据成员)受到一定的限制;函数中没有this 指针,一般数据成员不可以使用,习惯是静态函数访问静态数据成员。

(参见上面例子)

第七章:类的定义及其类对象的封装性

Page 26: 面向对象程序设计 理论篇

《面向对象程序设

计》

《面向对象程序设

计》

◆ 7 . 6 类对象作为成员 1 、类对象成员的定义与 标准数据类型相同;

2 、类( A )对象成员( b )的初始化,可以在类 A 构造的同时构造(初始化) b; 〖举例〗

方法一: b 是对象, A::A( ) : b( XX ) 或 A::A( int zz ) : b(zz);

方法一: b 是对象指针,除 采用方法一外,可以利用对象指针 pB 开辟空间时构造; pB = new B(zz);

第七章:类的定义及其类对象的封装性

Page 27: 面向对象程序设计 理论篇

《面向对象程序设

计》

《面向对象程序设

计》

◆ 7 . 7 对象数组 1 、每个数组元素都是对象的数组是对象数组;

2 、对象对 应的类必须有一个不带参数或带缺省参数的构造函数,因为在定义对数组时无法给构造函数 传递参数;

A a[10];

A* pA = new A[10];

3 、区别于“数组对象”

第七章:类的定义及其类对象的封装性

Page 28: 面向对象程序设计 理论篇

《面向对象程序设

计》

《面向对象程序设

计》

◆ 7 . 8 C++ 中的封装性 封装实际上就是信息隐蔽。1 、对象的封装将对象的属性(数据内容)和作用于这 些属性上的作(函数内容)封装在一起,对象的使用 者只能通过提供它的接口(协议)使用这个对象。对象的内部是 被保护起来的,他的使用是通过发送消息——即调用公有成员函数完成的。2 、程序的 模块化文件(程序)的组 织形式( 1 )类说明(声明)文件( *.h )( 2 )类实现(定义)文件( *.cpp )( 3 )常量或宏定义文件( *.h )( 4 )类的使用文件( *.cpp )

第七章:类的定义及其类对象的封装性

Page 29: 面向对象程序设计 理论篇

《面向对象程序设

计》

《面向对象程序设

计》

◆ 7 . 9 实例分析 CGeoProject

CGeoIO

CGeoEdit

CGeoLine

CGeoPrjSet

CGeoSurface CGeoRegion CGeoRouteCGeoPoint CGeoGroup

CGeoMap

CGeoLayer

第七章:类的定义及其类对象的封装性

Page 30: 面向对象程序设计 理论篇

《面向对象程序设

计》

《面向对象程序设

计》

◆ 总结:

• 类的组成及定义• 构造函数和析构函数的使用• 动态分配机制• 静态成员变量和静态成员函数• 类对象成员的构造

第七章:类的定义及其类对象的封装性

Page 31: 面向对象程序设计 理论篇

《面向对象程序设

计》

《面向对象程序设

计》

◆ 7 . 1 C++ 类的构成

class GeoPoint{private: // 可以省略

double x;double y;double z;

public:void SetValue(double x ,double y,double z);void GetValue(double& x ,double& y, double& z);

protected:void ChangePoint();

};

struct GeoPoint {

double x;double y;double z;

};

返回

第七章:类的定义及其类对象的封装性

Page 32: 面向对象程序设计 理论篇

《面向对象程序设

计》

《面向对象程序设

计》

◆ 7 . 4 构造函数与析构函数

GeoObject* pObj = new GeoObject;

pObj->name = new char[80];

pObj-> nPointNum = 100;

pObj-> pPoints = new POINT[100]; 返回

struct GeoObject

{

char* name;

int nPointNum;

POINT* pPoints;

};

第七章:类的定义及其类对象的封装性

Page 33: 面向对象程序设计 理论篇

《面向对象程序设

计》

《面向对象程序设

计》

if( NULL == m_ulIdx )

{

......

m_ulIdx = new unsigned long*[1024];

for(int m=0; m<1024; m++)

{

......

unsigned long midnum=0;

fread(&midnum,sizeof(unsigned long),1,indexfp);

m_ulIdx[m]=new unsigned long[midnum+1];

memset(m_ulIdx[m],0x00,sizeof(unsigned long)*(midnum+1));

m_ulIdx[m][0]=midnum;

fread(&m_ulIdx[m][1],sizeof(unsigned long),midnum,indexfp);

......

}

}

◆ 7 . 4 构造函数与析构函数 if( NULL != m_ulIdx )

{

for(int m=0;m<1024;m++)

{

delete[ ] m_ulIdx[m];

m_ulIdx[m] = NULL;

}

delete[ ] m_ulIdx;

m_ulIdx=NULL;

}

返回

第七章:类的定义及其类对象的封装性

Page 34: 面向对象程序设计 理论篇

《面向对象程序设

计》

《面向对象程序设

计》

◆ 7 . 4 构造函数与析构函数

返回

CGeoLayer ** m_pGeoLayer = NULL;

m_pGeoLayer = new CGeoLayer*[m_strarrayLandFile.GetSize()];

for(int ii=0;ii<m_strarrayLandFile.GetSize();ii++)

{

m_pGeoLayer[ii] = new CGeoLayer(m_strarrayLandFile.GetAt(ii));

m_pGeoLayer[ii]->SetGeoMap(this);

}

if(NULL != m_pGeoLayer){

for(int ii=0;ii<m_strarrayLandFile.GetSize();ii++){

delete m_pGeoLayer[ii];m_pGeoLayer[ii] = NULL;

}delete [] m_pGeoLayer;m_pGeoLayer = NULL;

}

第七章:类的定义及其类对象的封装性

Page 35: 面向对象程序设计 理论篇

《面向对象程序设

计》

《面向对象程序设

计》

void Office::Add()

{

person_count += nPerson;

// 有问题,没有 this 指针,使用nPerson错误。

}

void Office::Add(office p)

{

person_count += p .nPerson;

//正确,通过传递成员变量}

Office b1; //1.1

Office b2; //1.2

Office b3; //1.3

Office b4; //1.4

◆ 7 . 5 静态成员 class Office

{

static int person_count;

int nPerson;

public:

Office();

~ Office(){};

static void Add();

};

int Office:: person_count = 0;

Office:: Office ()

{

nPerson = 2;

person_count += 1;

}返回

第七章:类的定义及其类对象的封装性

Page 36: 面向对象程序设计 理论篇

《面向对象程序设

计》

《面向对象程序设

计》

◆ 7 . 6 类对象作为成员 Class B

{

int z;

B();

~B();

};

Class A

{

B b;

B* pB;

int x;

int y;

A();

A(int zz);

};

A::A():b(10)

{

}

A::A(int zz):b(zz)

{

}

A::A(int zz)

{

pB = new B(zz);

}

返回

第七章:类的定义及其类对象的封装性