C++ 中的类可以是对同一类型事物进行抽象处理后的结果,也可以是一个层次结构中的不同层次节点。
例如,将客观世界看成一个 Object 类,动物是客观世界的一部分,定义为 Animal 类;狗是一种哺乳动物,是动物类的子类,定义为 Dog 类;鱼也是一种动物,定义为 Fish 类。
上述各类之间的层次关系如下图所示:
图 1 类的层次关系
类是一种新的数据类型,它和结构体有些相似,是由不同数据类型组成的集合体。不同的是,类比结构体增加了操作数据的行为,这个行为就是成员函数。
C++类的声明与定义
类在使用前,需要先进行声明和定义。C++ 中,使用 class 关键字定义一个类。类的定义格式如下:
class 类名标识符
{
[public]
[成员变量的声明]
[成员函数的声明]
[private]
[成员变量的声明]
[成员函数的声明]
[protected:]
[成员变量的声明]
[成员函数的声明]
};
大括号内被称为类体或类空间,是定义和声明类成员的地方。关键字 public、private、protected 是类成员访问修饰符,限定了类成员的访问权限。大括号后要有分号。
类成员包括两类,分别是成员变量和成员函数:
成员变量(又称为数据成员)表示类的属性,可以是整型、浮点型、字符型、数组、指针和引用等,也可以是对象;
成员函数(又称为方法)表示类的行为。
注意,其他类的对象可以作为类的成员,自身类的对象不可以作为类的成员,但自身类的指针或引用可以作为类的成员。
例如,下面给出一个员工信息类的定义:
class CPerson //定义 CPerson 类
{
//声明 4 个成员变量
int m_index; //声明 m_index,表示员工编号
char m_cName[25]; //声明 m_cName[25],表示员工姓名
short m_shAge; //声明 m_shAge,表示员工工龄
double m_dSalary; //声明 m_dSalary,表示员工薪资
//声明 8 个成员函数
short getAge(); //声明 getAge(),表示获取员工工龄
int setAge(short sAge) //声明 setAge(),设置员工工龄
int getIndex(); //声明 getIndex(),表示获取员工编号
int setIndex(int index); //声明 setIndex(),表示设置员工编号
char *getName(); //声明 getName(),表示获取员工姓名
int setName(char cName[25]); //声明 setName(),表示设置员工姓名
double getSalary(); //声明 getSalary(),表示获取员工薪资
int setSalary(double dSalary); //声明 setSalary(),表示设置员工薪资
};
上面的代码中,CPerson 是定义的员工信息类,大括号中包含了 4 个成员变量,分别表示 CPerson 类的 4 个属性;还包含 8 个成员函数,表示 CPerson 类的 8 种行为。
C++类的实现
CPerson 类中声明了类的成员,下面介绍如何定义类中的方法(即成员函数)。
1) 将类的成员函数都定义在类体内。例如,以下代码都在 Person.h 头文件内,类的成员函数都定义在类体内。
#include
#include
#include
class CPerson //定义 CPerson 类
{
public:
int m_index;
char m_cName[25];
short m_shAge;
double m_dSalary;
short getAge() //定义 getAge(),表示获取员工工龄
{
return m_shAge;
}
int setAge(short sAge) //定义 setAge(),表示设置员工工龄
{
m_shAge=sAge;
return 0;
}
int getIndex() //定义 getIndex(),表示获取员工编号
{
return m_index;
}
int setIndex(int index) //定义 setIndex(),表示设置员工编号
{
m_index=index;
return 0;
}
char *getName() //定义 getName(),表示获取员工姓名
{
return m_cName;
}
int setName(char cName[25]) //定义 setName(),表示设置员工姓名
{
strcpy(m_cName,cName);
return 0;
}
double getSalary() //定义 getSalary(),表示获取员工薪资
{
return m_dSalary;
}
int setSalary(double dSalary) //定义 setSalary(),表示设置员工薪资
{
m_dSalary=dSalary;
return 0;
}
};
2) 将类体内成员函数的实现放在类体外,此时需要使用域限定符“::”标识该方法属于哪个类。放在类体内和类体外定义的效果是一样的。
class CPerson //定义 CPerson 类,声明 4 个成员变量和 8 个成员函数
{
public:
int m_index;
char m_cName[25];
short m_shAge;
double m_dSalary;
short getAge();
int setAge(short sAge);
// 省略其他成员函数的声明代码
};
// CPerson 类成员函数的实现部分
short CPerson::getAge() //定义 getAge(),在类体外定义要使用域限定符“::”
{
return m_shAge;
}
int CPerson::setAge(short sAge) //定义 setAge(),在类体外定义要使用域限定符“::”
{
m_shAge=sAge;
return 0;
}
// 省略其他成员函数的实现代码
除此以外,C++ 中还可以将函数的声明和定义放在不同的文件内。一般在头文件中放入函数的声明部分,在实现文件中放入成员函数的实现部分。同样,也可以将类的定义放在头文件中,将类的成员函数的实现放在实现文件内。存放类的头文件和实现文件最好和类名相同或相似。
例如,将 CPerson 类的声明部分放在 Person.h 文件内,程序代码如下:
#include
#include
#include
class CPerson //定义 CPerson 类,声明 4 个成员变量和 8 个成员函数
{
public:
int m_index;
char m_cName[25];
short m_shAge;
double m_dSalary;
short getAge();
int setAge(short sAge);
int getIndex();
int setIndex(int index);
char *getName();
int setName(char cName[25]);
double getSalary();
int setSalary(double dSalary);
};
将 CPerson 类的实现部分放在 Person.cpp 文件内,程序代码如下:
#include "Person.h" //CPerson 类成员函数的实现部分
short CPerson::getAge()
{
return m_shAge;
}
int CPerson::setAge(short sAge)
{
m_shAge=sAge;
return 0;
}
//省略其他成员函数的实现代码
整个工程的所有文件如下图所示:
图 2 工程所有文件
注意,类的 .h 文件名不需要和 .cpp 文件名相同,但是在 .cpp 文件中包含头文件时,一定要和 .h 文件名一致。
关于类的实现,有以下两点说明:
1) 类的成员变量需要初始化,成员函数还需要添加实现代码。另外,类的成员变量不能在类的声明中初始化。例如,下面的代码将无法通过编译:
class CPerson
{
int m_index=1; //错误写法,不能在类的声明中初始化
char m_cName[25]="Mary"; //错误写法,不能在类的声明中初始化
short m_shAge=22; //错误写法,不能在类的声明中初始化
double m_dSalary=1700.00; //错误写法,不能在类的声明中初始化
short getAge();
int setAge(short sAge);
//省略其他成员函数的声明代码
};
2) 空类是 C++ 中最简单的类,通常用来占位。其声明方式如下:
class CPerson{};
程序开发中,空类表示此处暂不定义,后续根据需要再定义其类成员及方法实现。
C++对象的声明和引用
类是一种数据类型,用户定义类后,即可通过类名声明对象。语法格式如下:
类名 对象名
例如,使用前面定义的 CPerson 类声明对象:
CPerson p; //声明对象 p
CPerson p1,p2,p3. //声明 3 个对象 p1、p2、p3
对象的引用方式有两种:使用成员运算符“.”和使用指向运算符“->”。
1) 使用“.”运算符引用成员变量和成员函数,语法形式如下:
对象名.成员名
对象名.成员名(参数表) //参数表
例如,可通过 p.m_index、p.getAge() 引用类 p 中的成员。
2) 对象数组、对象指针和引用形式的对象,需要使用指向运算符“->”运算符进行引用。例如,声明一个对象指针 p,使其指向对象 m_iIndex,代码如下:
CPerson *p;
p->m_iIndex;
下面两种引用成员变量的形式是等价的:
对象指针名->数据成员名
(*对象指针名).数据成员名
同样,下面两种引用成员函数的形式也是等价的:
对象指针名->成员函数名(参数表)
(*对象指针名).成员函数名(参数表)
例如,可通过 (*p).m_iIndex 或 p->m_iIndex 引用类 p 中的成员。
【实例】在本实例中,利用前文声明的 CPerson 类定义对象,然后使用该对象引用其成员。程序代码如下:
#include
#include "Person.h"
using namespace std;
int main()
{
int iResult=-1;
CPerson p; //声明对象 p,属于 CPerson 类
iResult=p.setAge(25); //引用 p.setAge(),设置工龄
if(iResult>=0)
cout << "m_shAge is:" << p.getAge() << endl; //引用 p.setAge(),输出工龄
iResult=p.setIndex(0); //引用 p.setIndex(),设置员工编号
if(iResult>=0)
cout << "m_index is:" << p.getIndex() << endl; //引用 p.getIndex(),输出员工编号
char bufTemp[]="Mary";
iResult=p.setName(bufTemp); //引用 p.setName(),设置姓名
if(iResult>=0)
cout << "m_cName is:" << p.getName() << endl; //引用 p.getName(),输出姓名
iResult=p.setSalary(1700.25); //引用 p.setSalary(),设置薪资
if(iResult>=0)
cout << "m_dSalary is:" << p.getSalary() << endl; //引用 p.getSalary(),输出薪资
}
程序中首先使用 CPerson 类定义对象 p,然后引用类中的成员函数。p.setAge(25) 引用类中的 setAge() 成员函数,传递实参,设置员工工龄。函数返回值赋给 iResult 变量,并通过 iResult 判断函数 setAge() 为数据成员赋值是否成功,如果成功,使用 p.getAge() 得到赋值数据并显示输出。
之后使用对象 p 依次引用成员函数 setIndex()、setName()和setSalary(),然后通过对 iResult 变量的判断,决定是否引用成员函数 getIndex()、getName() 和 getSalary()。