在面向过程的结构化程序设计中,程序模块是由函数构成,函数将对数据处理的语句放在函数体内,完成特定的功能,数据则通过函数参数传递进入函数体。
在面向对象的程序设计中,程序模块是由类构成的。类是对逻辑上相关的函数与数据的封装,它是对问题的抽象描述。
面向对象的程序设计方法就是运用面向对象的观点来对现实世界中的各种问题进行抽象,然后用计算机程序来描述并解决该问题,这种描述和处理是通过类与对象实现的。
类与对象是C++程序设计中最重要的概念。
简单讲,类是一个包含函数的结构体。因此,类的定义与结构类型的定义相似,其格式如下:
class 类名
{
public:
公有数据成员或公有函数成员的定义;
protected:
保护数据成员或保护函数成员的定义;
private:
私有数据成员或私有函数成员的定义;
};
说明: 关键字class表明定义的是一个类; 类名是类的名称,应是一个合法的标识符; public、protected、private为存取控制属性(访问权限),用来控制对类的 成员的存取。如果前面没有标明访问权限,默认访问权限为private。 类的成员有数据成员与函数成员两类,类的数据成员和函数成员统称为类的 成员,类的数据成员一般用来描述该类对象的属性,称为属性;函数成员是描 述类行为,称作方法。函数成员由函数构成,这些作为类成员的函数因此也叫函数成员。
1. 数据成员
类定义中的数据成员描述了类对象所包含的数据类型,数据成员的类型可以是C++基本数据类型,也可以是构造数据类型。
struct Record
{
char name[20];
int score;
};
class Team {
private:
int num; //基本数据类型
Record *p; //构造数据类型
};
class Team; //已定义的类
class Grade {
Team a; // 使用了已定义的类类型
Grade *p; // 使用正在定义的类类型定义指针成员
Grade &r; // 使用正在定义的类类型定义引用成员
Grade b; // 错误! 使用了未定义完整的类Grade 定义数据成员
};
注意: 因为类只是一种类型,类中的数据成员不占内存空间,因此在定义数据成员 时不能给数据成员赋初值。 类的数据成员除了可以使用前面讲述的C++类型外,还可以使用已定义完整的 类类型。 在正在定义的类中,由于该类型没有定义完整,所以不能定义该类类型的变 量,只能定义该类类型的指针成员以及该类类型的引用成员。
2. 成员函数
作为类成员的成员函数描述了对类中的数据成员实施的操作。成员函数的定义、声明格式与非成员函数(全局函数)的格式相同。成员函数可以放在类中定义,也可以放在类外。放在类中定义的成员函数为内联(inline)函数。
Clock类中的成员函数就是放在类内定义的。
C++可以在类内声明成员函数的原型,在类外定义函数体。这样做的好处是相当于在类内列了一个函数功能表,使我们对类的成员函数的功能一目了然,避免了在各个函数实现的大堆代码中查找函数的定义。在类中声明函数原型的方法与一般函数原型的声明一样,在类外定义函数体的格式如下:
返回值类型 类名 :: 成员函数名(形参表)
{
函数体;
}
::是类的作用域分辨符,用在此处,放在类名后成员函数前,表明后面的成员函数属于前面的那个类。
Clock类中的成员函数可以在类中声明:
class Clock {
private:
int H,M,S;
public:
void SetTime(int h,int m,int s); //声明成员函数
void ShowTime(); //声明成员函数
};
在类外实现成员函数如下:
void Clock::SetTime(int h,int m,int s)
{
H=h,M=m,S=s;
};
void Clock:: ShowTime()
{
cout<<H<<":"<<M<<":"<<S<<endl;
}
如果要将类外定义的成员函数编译成内联函数,可以在类外定义函数时,函数的返回类型前加上inline; 下面将ShowTime()定义成内联函数,与在类内定义成员函数的效果相同。
inline void Clock::ShowTime()
{
cout<<H<<":"<<M<<":"<<S<<endl;
}
3. 类作用域
类是一组数据成员和函数成员的集合,类作用域作用于类中定义的特定的成员,包括数据成员与成员函数,类内的每一个成员都具有类作用域。实际上,类的封装作用也就是限制类的成员其访问范围局限于类的作用域之内。
class Clock {
private:
int H,M,S;
public:
Clock AddTime(Clock C2){ // 形参为Clock类型的变量
Clock T; // 函数体中定义了Clock类型的变量
...
return T; // 返回类型为Clock类型
}
};
注意: 在成员函数中不仅可以自由使用类的成员,还可以使用该类定义变量(对象),通过变量使用成员。其原因是函数在调用时才在栈内存中建立函数体中的变量(包括实参),这时类已经定义完毕,当然可以使用已定义完整的类类型的变量。
对象的建立与使用
类相当于一种包含函数的自定义数据类型,它不占内存,是一个抽象的“虚”体,使用已定义的类建立对象就像用数据类型定义变量一样。 对象建立后,对象占据内存,变成了一个“实”体。类与对象的关系就像数据类型与变量的关系一样。其实,一个变量就是一个简单的不含成员函数的数据对象。
类名 对象名;
其中,对象名可以是简单的标识符,也可以是数组。
在建立对象后,就可以通过对象存取对象中的数据成员,调用成员函数。存取语法如下:
对象名.属性
对象名.成员函数名(实参1, 实参2,…,)
例如,通过对象MyClock使用成员函数SetTime()的方式如下: MyClock.SetTime(8,30,30); 至于对数据成员H、M、S的存取,因其存取权限为pravate而被保护, 所以不能进行直接存取。
注意: 为节省内存,编译器在创建对象时,只为各对象分配用于保存各对象数据成员初始化的值,并不为各对象的成员函数分配单独的内存空间,而是共享类的成员函数定义,即类中成员函数的定义为该类的所有对象所共享,这是C++编译器创建对象的一种方法,在实际应用中,我们仍要将对象理解为由数据成员和函数成员两部分组成。