程序设计B
1. 类的定义
-
类是对具有相同属性和行为的一类客观事物的概括描述。是用户自定义的数据类型(程序设计语言角度)
-
类的定义包括行为和属性两个部分。
-
属性以数据表示,行为通过函数实现。
C++类定义的格式:
class 类名
{
public:
公有数据成员和成员函数;
protected:
保护数据成员和成员函数;
private:
私有数据成员和成员函数;
};分号不得省略!!!
类定义举例
class Student //定义学生类Student
{
public: //声明类成员
void display();
private:
string name;
string id;
char sex;
int age;
double score;
}; //类定义以分号结束
注意事项
-
类的数据成员可以是其他类的对象,但不能以类自身的对象作为本类的成员,而类自身的指针和引用可以作为类的成员。
-
类首字母大写
-
数据成员私有
-
成员函数共有
-
类定义必须以分号“;”结束。
-
类与结构体的区别:
没有明确指定类成员的访问权限时,C++结构体的成员是公有的,而类的成员是私有的。
2. 访问控制
类的访问属性有:
- Public
- Protected
- Private
各种访问方式的功能如下表
访问控制 | 含义 | 属性 |
---|---|---|
public | 公有成员 | 类的外部接口 |
protected | 保护成员 | 仅允许本类成员函数及派生函数访问 |
private | 私有成员 | 仅允许本类成员函数访问 |
3. 成员函数
类的成员函数是通过操纵数据成员实现类的行为。
一般将成员函数声明为函数原型,在类外具体实现成员函数。
成员函数的定义
返回值类型 类名::成员函数名(参数表)
{
函数体
}
4. 对象
- 对象是类的实例或实体。
- 类与对象的关系,如同C++基本数据类型和该类型的变量之间的关系。
对象的定义
格式如下:
类名 对象名1,对象名2,…,对象名n;
定义对象应注意
- 必须在定义了类之后,才可以定义类的对象。
5. 类成员的访问
对象成员的访问包括:
- 圆点访问形式:对象名.公有成员
- 指针访问形式
指针访问形式
对象指针变量名->公有成员
C++中,类的名字就是用户自定义的类型的名字。可以象使用基本类型那样来使用它。
类定义和使用时应注意:
- 在类的定义中不能对数据成员进行初始化。
- 类的任何成员都必须指定访问属性,一般将数据成员定义为私有成员或保护成员,将成员函数定义为公有成员。
- 类中的数据成员可以是C++语法规定的任意数据类型。
- 类的成员可以是其他类的对象,称为类的组合。但不能以类自身的对象作为本类的成员。
- 类定义必须以分号“;”结束
- class与struct的不同:
① class中,成员缺省情况是private。
② struct中,成员缺省情况是public。
内联函数
内联函数作用
减少频繁调用小子程序的运行的时间开销
内联函数机制
编译器在编译时,将内联函数的调用以相应代码代替
内联函数声明
inline 函数原型
注:
内联函数仅在函数原型作一次声明。
适用于只有1 ~ 5行的小函数
不能含有复杂结构控制语句 ,不能递归调用
函数重载
- 参数个数相同
- 参数类型不同
6. 构造函数和析构函数
构造函数:
- 构造函数是用于创建对象的特殊的成员函数
当创建对象时,系统自动调用构造函数 - 构造函数的作用是:
为对象分配空间;对数据成员赋初值;请求其他资源。 - 用户没有定义的构造函数时,系统自动提供缺省版本的构造函数
- 构造函数名与类名相同:类名
- 构造函数可以重载
- 构造函数可以有任意类型的参数,但没有返回类型
析构函数:
- 析构函数是用于取消对象的成员函数
当一个对象作用结束时,系统自动调用析构函数 - 析构函数的作用是进行对象消亡时的清理工作
- 没有用户定义析构函数时,系统提供缺省版本的析构函数
- 析构函数名为: ~ 类名
- 析构函数没有参数,也没有返回类型
默认构造函数
如果类中没有定义构造函数,系统将自动生成一个默认形式的构造函数,用于创建对象,默认构造函数形式:
类名::类名(){}
利用构造函数创建对象两种方法
1.利用构造函数直接创建对象.其一般形式为:
类名 对象名[(实参表)];
不带参数:
当用户没定义构造函数时,调用默认的构造函数;当用户定义了构造函数时,调用无参的构造函数(没有无参构造函数时要出错!系统不会调用默认构造函数。
带实参表:
系统按照重载函数匹配原则,调用对应的构造函数;
2.利用构造函数创建对象时,通过指针和new来实现。其一般语法形式为:
类名 *指针变量 = new 类名[(实参表)];
例如:
Date *date1=new Date(1998,4,28);
就创建了对象(*date1)。
构造函数的初始化列表--------数据成员的初始化
构造函数初始化成员有两种方法:
A.使用构造函数的函数体进行初始化
B.使用构造函数的初始化列表进行初始化
格式:
funname(参数列表):初始化列表
{ 函数体,可以是空函数体 }
初始化列表的形式:
成员名1(形参名1),成员名2(形参名2),成员名n(形参名n)
必须使用参数初始化列表对数据成员进行初始化的几种情况
- 数据成员为常量
- 数据成员为引用类型
- 数据成员为没有无参构造函数的类的对象
类成员的初始化的顺序:
按照数据成员在类中的声明顺序进行初始化,与初始化成员列表中出现的顺序无关
带默认值的构造函数
#include <iostream>
using namespace std;
class Box
{
public:
Box(); //定义了全部带默认值的构造函数,不能再定义无参 构造函数
Box(int h=10,int w=10 , int l=10); //只能在声明时指定默认值
int volume();
private:
int height,width, length;
};
析构函数
对象生存期结束时,需要做清理工作,比如:释放成员(指针)所占有的存储空间
析构函数可以完成上述工作。
析构函数自动调用(隐式调用)
定义格式如下(类外实现):
类名::~类名()
{
函数语句
}
析构函数有以下一些特点:
① 析构函数与构造函数名字相同,但它前面必须加一个波浪号(~);
② 析构函数没有参数,也没有返回值,而且不能重载。因此在一个类中只能有一个析构函数;
③ 当撤消对象时,编译系统会自动地调用析构函数。
默认析构函数
若没有显式定义析构函数,则系统自动生成一个默认形式的析构函数。
系统自动生成的默认构造函数形式如下:
类名::~类名(){}
一般情况下,可以不定义析构函数
但如果类的数据成员中包含指针变量是从堆上进行存储空间分配的话,需要在析构函数中进行存储空间的回收