第九章类和对象.docx

上传人:b****5 文档编号:6431661 上传时间:2023-01-06 格式:DOCX 页数:34 大小:25.71KB
下载 相关 举报
第九章类和对象.docx_第1页
第1页 / 共34页
第九章类和对象.docx_第2页
第2页 / 共34页
第九章类和对象.docx_第3页
第3页 / 共34页
第九章类和对象.docx_第4页
第4页 / 共34页
第九章类和对象.docx_第5页
第5页 / 共34页
点击查看更多>>
下载资源
资源描述

第九章类和对象.docx

《第九章类和对象.docx》由会员分享,可在线阅读,更多相关《第九章类和对象.docx(34页珍藏版)》请在冰豆网上搜索。

第九章类和对象.docx

第九章类和对象

类与对象

传统的结构化语言都是采用面向过程的方法来解决问题。

在面向过程的程序设计方法中,代码和数据是分离的,因此,程序的可维护性较差。

面向对象(ObjectOriented)程序设计方法则是把数据及处理这些数据的函数封装到一个类中,类是C++的一种数据类型,而使用类的变量则称为对象。

函数是将逻辑上有关的语句和数据集合在一起,主要用于执行;而类则是逻辑上有关的函数及其数据的集合,它主要不是用于执行,而是提供所需要的资源。

1.类的定义

在使用一个类之前必须先定义类。

例如在C语言里声明一个结构体类型:

structstudent

{intnum

charname[10];

charsex;

};

structstudentstudent1,student2;

 

现在我们声明一个类:

classstud//以class开头

{intnum

charname[10];

charsex;//以上3行是数据成员

voiddisplay()//这是成员函数

{cout<<”num:

”<

cout<<”name:

”<

cout<”sex:

”<

}//以上4行是操作代码

};

studstud1,stud2;//定义了两个stud类的对象

定义一个类的语法格式如下:

class类名:

基类名

{

private:

私有成员数据及函数;

protected:

保护成员数据及函数;

public:

公共成员数据及函数;

}[类的对象声明];

一个类含有私有成员(private)、保护成员(protected)和公共成员(public)三部分。

默认时在类中定义的项都是私有的。

私有变量和函数只能被该类本身的成员函数存取或调用;保护成员除可以被本类中的成员函数访问外,还可以被本类派生的类的成员函数访问,因此用于类的继承;公共成员可以被本类以外的函数访问,是类与外部的接口。

类是面向对象程序设计最基本的单元,在设计面向对象程序时,首先要以类的方式描述实际待解决的问题,也就是将问题所要处理的数据定义成类的私有或公共类型的数据,同时将处理问题的方法定义成类的私有或公有的成员函数。

类也可以嵌套声明。

对象

对象是声明为类类型的一个数据项,是类的实际变量,有时也称为类的实例(Instance)。

方法:

类中的成员函数称为“方法”,“方法”是对数据的操作。

方法的具体实现既可以在类的定义内部完成,也可以在类的定义之外进行,而且方法的具体实现既可以和类的定义放在同一个源文件中,也可以放在不同的源文件中。

消息:

外界是通过发“消息”来激活有关方法的。

所谓“消息”,其实就是一个命令,由程序语句来实现。

例如想输出对象stud1中的学生学号、姓名、性别等信息,可以在程序中写

stud1.display();

这就是向对象stud1发出的一个“消息”,通知它执行display“方法”。

例1-1:

Lt1-1.cpp

#include

#include

constdoubleANG_TO_RAD=0.0174532925;

//定义弧度和度之间的转换比例,即弧度的值

classangle//定义类angle

{doublevalue;//类angle的私有数据成员

public:

//类angle的公共数据成员

voidSetValue(double);

doubleGetSine(void);

}deg;//声明类angle的对象deg

voidangle:

:

SetValue(doublea)//类angle的成员函数SetValuede的具体实现

{value=a;

}

doubleangle:

:

GetSine(void)//类angle的成员函数GetSine的具体实现

{doubletemp;

temp=sin(ANG_TO_RAD*value);

returntemp;

}

voidmain()

{deg.SetValue(60.0);//给类angle的成员变量Value赋值

cout<<"Thesineoftheangleis:

";

cout<

}

运行结果为:

Thesineoftheangleis:

0.866025

 

又例:

#include

#include

constdoubleANG_TO_RAD=0.0174532925;

//定义弧度和度之间的转换比例,即弧度的值

classangle//定义类angle

{

doublevalue;//类angle的私有数据成员

public:

//类angle的公共数据成员

voidSetValue(double);

doubleGetSine();//void可以不要

}deg;//声明类angle的对象deg

voidangle:

:

SetValue(doublea)//类angle的成员函数SetValuede的具体实现

{value=a;

}

doubleangle:

:

GetSine()//类angle的成员函数GetSine的具体实现

{doubletemp;

temp=sin(ANG_TO_RAD*value);

returntemp;

}

voidmain()

{deg.SetValue(60.0);//给类angle的成员变量Value赋值

cout<<"Thesineoftheangleis:

";

cout<

}

运行结果为:

Thesineoftheangleis:

0.866025

 

2.内联函数

调用函数时需要一定的时间,如果有的函数需要频繁使用,则所用时间会很长,从而降低程序的执行效率。

C++提供一种提高效率的方法,即在编译时将调用函数的代码嵌入到主调函数中。

这种嵌入到主调函数中的函数称为“内联函数”(inlinefunction),又称“内嵌函数”或“内置函数”。

例1-2:

Lt1-2.cpp

#include

inlineintmax(inta,intb,intc)//这是一个内联函数,求3个整数中的最大者

{if(b>a)a=b;

if(c>a)a=c;

returna;

}

voidmain()

{inti=7,j=10,k=25,m;

m=max(i,j,k);

cout<<"max="<

}

运行结果为:

max=25

类的方法也可以声明和定义成内联函数。

可以使用下面两种格式定义类的内联函数:

(1)把函数原型声明和方法的定义合并,放入类定义中。

例1-3:

Lt1-3.cpp

#include

#include

constdoubleANG_TO_RAD=0.0174532925;

classangle//定义类angle

{doublevalue,temp;//定义私有数据成员

public:

doubleGetSine(doublea)//定义内联函数

{value=a;

temp=sin(ANG_TO_RAD*value);

returntemp;

}

}deg;

voidmain()

{

cout<<"Thesineoftheangleis:

";

cout<

}

运行结果为:

Thesineoftheangleis:

0.866025

 

(2)当在函数的外部定义时,把关键字inline加在函数定义之前。

例1-4:

Lt1-4.cpp

#include

#include

constdoubleANG_TO_RAD=0.0174532925;

//定义弧度和度之间的转换比例,即弧度的值

classangle//定义类angle

{doublevalue;//类angle的私有数据成员

public:

//类angle的公共数据成员

voidSetValue(double);

doubleGetSine(void);

}deg;//声明类angle的对象deg

inlinevoidangle:

:

SetValue(doublea)//定义内联函数

{value=a;

}

inlinedoubleangle:

:

GetSine(void)//定义内联函数

{doubletemp;

temp=sin(ANG_TO_RAD*value);

returntemp;

}

voidmain()

{deg.SetValue(60.0);//给类angle的成员变量Value赋值

cout<<"Thesineoftheangleis:

";

cout<

}

运行结果为:

Thesineoftheangleis:

0.866025

 

3.构造函数和析构函数

构造函数

在建立一个对象时,常常需要做某些初始化的工作(例如对数据赋予初值),C++提供了一种特殊的成员函数----构造函数(constructor)。

这种函数与其他成员不同,不需要用户发“消息”来激活它,而是在建立对象时自动执行。

构造函数是由用户定义的,它必须与类名同名,以便系统能识别它并把它作为构造函数。

下面是一个不带构造函数的类:

classstud//以class开头

{intnum

charname[10];

charsex;//以上3行是数据成员

voiddisplay()//这是成员函数

{cout<<”num:

”<

cout<<”name:

”<

cout<”sex:

”<

}//以上4行是操作代码

};

studstud1;//定义了两个stud类的对象

现在我们在其中加入构造函数:

classstud//以class开头

{intnum;

charname[10];

charsex;//以上3行是数据成员

public:

stud()//定义构造函数,函数名与类名相同

{num=10010;

strcpy(name,”Wang_li”);

sex=’F’;

}//以上3行为给数据赋初值

voiddisplay()//定义成员函数

{cout<<”num:

”<

cout<<”name:

”<

cout<<”sex:

”<

}//以上3行是操作代码

};

studstud1;//在定义对象stud1时自动执行构造函数

构造函数不需用户调用,而是在定义一个对象时由系统自动执行,而且只能执行一次。

构造函数一般声明为public,无返回值,也不需加void类型声明。

下面写成一个完整的程序:

例1-5:

建立一个对象,输出学生的学号、姓名、性别。

Lt1-5.cpp

#include

#include

voidmain()

{classstud//声明一个类

{private:

intnum;

charname[10];

charsex;//以上3行是数据成员

public:

stud()//定义构造函数,函数名与类名相同

{num=10010;//给数据赋初值

strcpy(name,"Wang_li");

sex='F';

}//以上3行为给数据赋初值

voiddisplay()//定义成员函数,输出对象的数据

{cout<<"num:

"<

cout<<"name:

"<

cout<<"sex:

"<

}//以上3行是操作代码

};

studstud1;//在定义对象stud1时自动执行构造函数

stud1.display();//从对象外面调用display函数

}

运行结果为:

num:

10010

name:

Wang_li

sex:

F

如果要建立两个对象,分别对数据赋予初值,可将程序修改如下:

例1-6:

建立一个对象,输出学生的学号、姓名、性别。

Lt1-6.cpp

#include

#include

voidmain()

{classstud//声明一个类

{private:

intnum;

charname[10];

charsex;//以上3行是数据成员

public:

stud(intn,charnam[],chars)//定义构造函数,函数名与类名相同,有形参

{num=n;//给数据赋初值

strcpy(name,nam);

sex=s;

}//以上3行为给数据赋初值

voiddisplay()//定义成员函数,输出对象的数据

{cout<<"num:

"<

cout<<"name:

"<

cout<<"sex:

"<

}//以上3行是操作代码

};

studstud1(10010,"Wang_li",'f'),stud2(10011,"Zhang_fun",'m');

//在定义对象stud1、stud2时自动执行构造函数,同时给出相应实参

stud1.display();

stud2.display();//从对象外面调用display函数,分别输出两个学生的数据

}

运行结果为:

num:

10010

name:

Wang_li

sex:

f

num:

10011

name:

Zhang_fun

sex:

m

 

析构函数

析构函数(destructor)与构造函数相反,当对象脱离其作用域时(例如对象所在的函数已调用完毕),系统自动执行析构函数。

析构函数往往用来做“清理善后”的工作,通常用于释放分配给对象的存储空间。

析构函数也是类中的特殊成员函数,与定义它的类具有相同的名字,但要在前面加上一个波浪号(~),以区别于构造函数。

析构函数没有参数,也没有返回值,而且也不能重载,因此一个类中只能有一个析构函数。

和构造函数一样,如果在类的定义中不定义析构函数,编译系统将为之产生一个默认的析构函数,对于大多数类来说,默认的析构函数就能满足要求。

若在一个对象完成其操作之前还需要做一些内部处理,则应定义析构函数。

例1-7:

包含构造函数和析构函数的C++程序。

Lt1-7.cpp

#include

#include

classstud//声明一个类

{private:

intnum;

charname[10];

charsex;//以上3行是数据成员

public:

stud(intn,charnam[],chars)//定义构造函数,函数名与类名相同,有形参

{num=n;//给数据赋初值

strcpy(name,nam);

sex=s;

}//以上3行为给数据赋初值

~stud()//定义析构函数

{cout<<"Thisisadestructor"<

}

voiddisplay()//定义成员函数,输出对象的数据

{cout<<"num:

"<

cout<<"name:

"<

cout<<"sex:

"<

}//以上3行是操作代码

};

voidmain()

{studstud1(10010,"Wang_li",'f'),stud2(10011,"Zhang_fun",'m');

//在定义对象stud1、stud2时自动执行构造函数,同时给出相应实参

stud1.display();

stud2.display();//从对象外面调用display函数,分别输出两个学生的数据

}

运行结果为:

num:

10010

name:

Wang_li

sex:

f

num:

10011

name:

Zhang_fun

sex:

m

Thisisadestructor

Thisisadestructor

在本例中,析构函数并无任何实质上的作用,只是为了说明析构函数的使用方法。

例1-8:

包含构造函数和析构函数的C++程序。

Lt1-8.cpp

#include

#include

classstud//声明一个类

{char*p;

private:

intnum;

charname[10];

charsex;//以上3行是数据成员

public:

stud(intn,charnam[],chars)//定义构造函数,函数名与类名相同,有形参

{p=newchar[50];

num=n;//给数据赋初值

strcpy(name,nam);

sex=s;

}//以上3行为给数据赋初值

~stud()//定义析构函数

{cout<<"Thisisadestructor,deletethep"<

deletep;

}

voiddisplay()//定义成员函数,输出对象的数据

{cout<<"num:

"<

cout<<"name:

"<

cout<<"sex:

"<

}//以上3行是操作代码

};

voidmain()

{studstud1(10010,"Wang_li",'f'),stud2(10011,"Zhang_fun",'m');

//在定义对象stud1、stud2时自动执行构造函数,同时给出相应实参

stud1.display();

stud2.display();//从对象外面调用display函数,分别输出两个学生的数据

}

运行结果为:

num:

10010

name:

Wang_li

sex:

f

num:

10011

name:

Zhang_fun

sex:

m

Thisisadestructor,deletethep

Thisisadestructor,deletethep

以上程序中,成员函数是在类中定义的,如果成员函数的数目很多以及函数的长度很长,类的声明就会占很大的篇幅,不利于阅读程序。

可以在类的外面定义成员函数,而在类中只用函数的原型作声明。

例1-9:

在类的外面定义成员函数。

Lt1-9.cpp

#include

#include

classstud//声明一个类

{char*p;

private:

intnum;

charname[10];

charsex;//以上3行是数据成员

public:

stud(intn,charnam[],chars);//对构造函数的原型声明

~stud();//对析构函数的原型声明

voiddisplay();//对成员函数display的原型声明

};

stud:

:

stud(intn,charnam[],chars)

//对构造函数的定义,函数名与类名相同,有形参

{p=newchar[50];

num=n;//给数据赋初值

strcpy(name,nam);

sex=s;

}

stud:

:

~stud()//对析构函数的定义

{cout<<"Thisisadestructor,deletethep"<

deletep;

}

voidstud:

:

display()//对成员函数display的定义,输出对象的数据

{cout<<"num:

"<

cout<<"name:

"<

cout<<"sex:

"<

}//以上3行是操作代码

voidmain()

{studstud1(10010,"Wang_li",'f'),stud2(10011,"Zhang_fun",'m');

//在定义对象stud1、stud2时自动执行构造函数,同时给出相应实参

stud1.display();

stud2.display();//从对象外面调用display函数,分别输出两个学生的数据

}

运行结果为:

num:

10010

name:

Wang_li

sex:

f

num:

10011

name:

Zhang_fun

sex:

m

Thisisadestructor,deletethep

Thisisadestructor,deletethep

 

4.拷贝构造函数

拷贝构造函数是一种特殊的构造函数,其形参是本类对象的引用。

其作用是使用一个已经存在的对象去初始化另一个同类的对象。

拷贝构造函数具有以下特点:

⑴因为该函数也是一种构造函数,所以其函数名与类名相同,并且该函数

也没有返回值类型。

⑵该函数只有一个参数,并且是同类对象的引用。

⑶每个类都必须有一个拷贝构造函数。

程序员可以根据需要定义特定的

拷贝构造函数,以实现同类对象之间数据成员的传递。

如果程序员没有定义

类的拷贝构造函数,系统就会自动生成一个缺省的拷贝构

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 人文社科 > 设计艺术

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1