第9章 类和对象.docx
《第9章 类和对象.docx》由会员分享,可在线阅读,更多相关《第9章 类和对象.docx(15页珍藏版)》请在冰豆网上搜索。
第9章类和对象
第9章类和对象
本章目的:
1、理解面向对象程序设计的思想;
2、掌握类的声明和对象的定义方法;
3、掌握类成员函数的定义和调用方式以及类成员的引用方法。
9.1引言
到目前为止,我们所学习的C++的编程方法都属于面向过程的程序设计,不是真正意义上的C++。
这些知识对于解决规模较小的程序,程序设计人员可以将问题转化为若干个模块,通过实现每一个模块完成任务,但是这样的方法对于大规模的程序就显得力不从心了,那么从这次课开始我们就要进入C++的精髓部分——面向对象的程序设计。
该设计方法就是为解决大规模程序设计中出现的困难而产生的(具体思想详见附件)。
9.2类的声明和对象的定义
首先要明确类和对象的关系
Ø类是对象的抽象,对象是类的具体实例(instance);
Ø类是抽象的,不占用内存,而对象是具体的,占用存储空间。
在C++中,需要先声明一个类类型,然后再用它去定义若干个同类型的对象。
对象就是类类型的一个变量。
可以说类是对象的模板,是用来定义对象的一种抽象类型。
9.2.1声明类类型的方法
class类名
{private:
私有的数据和成员函数;
public:
公用的数据和成员函数;
protected:
受保护的数据和成员函数;
};
private、protected、public称为成员访问限定符(memberaccessspecifier)。
注意:
如果在类的定义中不指定限定符,则系统默认为私有的(private)。
说明:
(1)用private声明的成员称为私有成员,它只能被类中的成员函数访问,不能被类外访问,但可以被友元类的成员函数访问(后面讲到)。
(2)用protected声明的成员称为受保护成员,它不能被类外访问(这点与私有成员类似),但可以被派生类的成员函数访问(后面讲到)。
(3)用public声明的成员称为公有的成员,它可以被类中的成员函数访问,也可以被类外访问。
9.2.2对比结构体类型
structstudent
{intnum;
charname[20];
charsex
};
Studentstud1;
定义了结构体类型,并定义了结构体变量
classstudent
{intnum;
charname[20];
charsex;
voiddisplay()
{cout<<“num:
”<cout<<“name:
”<cout<<“sex:
”<}
};
studentstud1;
定义了类类型,以及类变量。
class中display为成员函数,函数体是具体的操作。
从上述可以看出,二者的区别为:
(1)结构体中只有成员变量,没有成员函数,而类中是二者兼有的;
(2)结构体中的成员没有访问限制,即均可通过结构体变量引用,而类成员只有public成员才可通过对象引用。
9.2.3对象的定义
与结构体变量定义的方法类似,同样也有三种方法:
A.先声明类类型,再定义对象
例如:
classstudent
{private:
…
public:
…
protected:
…
};
studentstud1
B.定义类类型的同时定义对象
例如:
classstudent
{private:
…
public:
…
protected:
…
}stud1;
C.不出现类名直接定义对象
例如:
class
{private:
…
public:
…
protected:
…
}stud1;
9.3类的成员函数
9.3.1成员函数的定义
类的成员函数(简称类函数)是函数的一种,它的用法和作用与普通函数基本上是一样的。
其定义方式如下:
(1)在类体中定义
例如:
函数返回值类型函数名(参数表)
{…//函数体
}
可以被指定为private(私有的)、public(共有的)或protected(受保护的)
(2)在类外定义
例如:
函数返回值类型类名:
:
函数名(参数表)
{…//函数体
}
在类外定义类函数时,必须在函数名前面加上类名和作用域限定符”:
:
”。
例如:
classstudent
{public:
voiddisplay();
private:
intnum;
charname[20];
charsex;
};
voidstudent:
:
display()
{cout<<“num:
”<cout<<“name:
”<cout<<“sex:
”<}
studentstud1;
(3)inline成员函数
Ø类的成员函数也可以指定为内置函数。
ØC++要求对一般的内置函数要用关键字inline声明,但对类内定义的成员函数,可以省略inline。
例如:
classstudent
{public:
inlinevoiddisplay();
private:
intnum;
charname[20];
charsex;
};
inlinevoidstudent:
:
display()
{cout<<“num:
”<cout<<“name:
”<cout<<“sex:
”<}
studentstud1;
如果在类外定义inline函数,则必须将类定义和成员函数定义放在同一个头文件中或同一个源文件中。
注意:
Ø类内定义的成员函数,默认为内置函数(inline)
Ø在类外定义时,在类体中要对函数作声明。
Ø如果在作用域运算符“∷”前没有类名,或者函数名前面既无类名又无作用域运算符“∷”,则表示该函数不属于任何类,为普通函数。
例如:
display()或display(),这里display()函数不属于任何类,为普通函数。
9.3.2成员函数的存储方式
用类定义对象时,系统会为每一个对象分配存储空间。
如果一个类包括了数据和函数,要分别为数据和函数的代码分配存储空间,如下图
但是存在这样一个情况:
不同对象的数据存储单元内存放的值不同,然而不同对象的函数代码是相同的,无论调用哪个对象的函数,所执行的代码内容均相同,为每个对象的代码都分配存储空间无疑造成的浪费。
那么,能否只用一段空间来存放这个共同代码段,在调用各对象的函数时,都去调用这个公共函数的代码?
C++正是这样做的,大大节省了存储空间,即如下图所示:
所以,每个对象所占的空间大小只取决于对象中数据成员所占的空间,而与函数无关。
例9.1如下程序段会输出什么?
classtime
{public:
inthour,minute,sec;
voidset()
{cin>>a>>b>>c;
}
};
cout<答案:
12
9.4对象成员的引用
现在大家来回忆一下对结构体成员的访问方法,其实对于访问对象中的成员,其方法与访问结构体成员类似,可归纳为:
(1)通过对象名和成员运算符访问对象中的成员;
(2)通过指向对象的指针访问对象中的成员;
(3)通过对象的引用变量访问对象中的成员。
例9.2对于如下类和对象的定义
classstudent
{public:
voiddisplay();
intnum;
charname[20];
charsex;
};
voidstudent:
:
display()
{cout<<“num:
”<cout<<“name:
”<cout<<“sex:
”<}
studentstud1,*p;
分别给出三种引用成员的方法。
(1)stud1.num=1001;
(2)p=&stud1;
p->num=1001;或(*p).num=1001;
(3)student&stud2=stud1;
stud2.num=1001;
思考:
如果将例9.2中程序做如下修改,上述引用还对吗?
为什么?
classstudent
{public:
voiddisplay();
private:
intnum;
charname[20];
charsex;
};
voidstudent:
:
display()
{cout<<“num:
”<cout<<“name:
”<cout<<“sex:
”<}
studentstud1,*p;
9.5类的封装性与信息隐蔽
(1)公用接口与私有实现的分离
Ø如果不必公开的信息,使用:
private
Ø要公开的,才使用:
public
(2)类声明和成员函数定义的分离
Ø为便于多个程序使用某类,应当把类的声明和成员函数的声明放在头文件中(即.h文件),把成员函数的定义放在另一个文件中(即.cpp文件)。
(3)面向对象程序设计中的几个名词
Ø“方法”(method):
“方法”是指对数据的操作(类的成员函数)。
一个“方法”对应一种操作。
Ø外界是通过发“消息”来激活有关方法的。
Ø“消息”:
其实就是一个命令,由程序语句来实现。
Ø发送“消息”:
一个对象通知另一个对象执行它的某条成员函数。
Ø接收“消息”:
一个对象接收到另一个对象要求它执行它的某条成员函数的信息。
例如对例9.2中的程序段,对象就是stud1,方法即为display(),而stud1.display()是消息
例9.3
#include
usingnamespacestd;
classTime
{public:
inthour;
intminute;
intsec;
};
intmain()
{Timet1;
cin>>t1.hour;
cin>>t1.minute;
cin>>t1.sec;cout<“;
cout<“;
cout<return0;
}
例9.4找出一个整型数组中元素的最大值(用类处理)。
//Array_max.h文件
classArray_max
{public:
voidset_value();
voidmax_value();
voidshow_value();
private:
intarray[10];
intmax;
};
//Array_max.cpp文件
#include
#include"Array_max.h"
usingnamespacestd;
voidArray_max∷set_value()
{inti;
for(i=0;i<10;i++)
cin>>array[i];}
voidArray_max∷max_value()
{inti;
max=array[0];
for(i=1;i<10;i++)
if(array[i]>max)max=array[i];
}
voidArray_max∷show_value()
{cout<<"max="<//main.cpp文件
#include
#include"Array_max.h"
usingnamespacestd;
intmain()
{Array_maxarrmax;
arrmax.set_value();
arrmax.max_value();
arrmax.show_value();
return0;
}
例9.5矩形类。
//CRectangle.h
classCRectangle
{
intx,y;
public:
voidset_values(int,int);
intarea()
{
return(x*y);
}
};
//CRectangle.cpp
#include"CRectangle.h"
voidCRectangle:
:
set_values(inta,intb)
{
x=a;
y=b;
}
//main.cpp
#include
#include"CRectangle.h"
usingnamespacestd;
intmain()
{
CRectanglerect;
rect.set_values(3,4);
cout<<"area:
"<return0;
}
程序运行结果:
例9.6复数类。
//Complex.h
#include
usingnamespacestd;
classComplex
{
private:
doublereal,imag;
public:
voidsetValue(double,double);
doublegetReal(){returnreal;}
doublegetImag(){returnimag;}
voiddisplay();
Complexconjugate();
};
//main.cpp
#include
#include"Complex.h"
usingnamespacestd;
voidmain()
{
Complexc,conj;
c.setValue(1.1,2.1);
cout<<"实部为:
"<cout<<"虚部为:
"<conj=c.conjugate();
cout<<"复数的";
c.display();
cout<<"共轭为:
";
conj.display();
cout<}
//Complex.cpp
#include"Complex.h"
voidComplex:
:
setValue(doublea,doubleb)
{
real=a;
imag=b;
}
voidComplex:
:
display()
{
cout<if(imag>0)
cout<<"+";
cout<cout<<"i";
}
ComplexComplex:
:
conjugate()
{
Complexcon;
con.real=real;
con.imag=-1.0*imag;
returncon;
}
程序运行结果: