在C++编程语言中,class是用于定义自定义数据类型的关键字,是面向对象编程范式的核心载体。它可以将相关的数据变量和用于处理这些数据的函数绑定在一起,形成一个独立的逻辑单元,让程序的结构更清晰,也便于代码的复用和维护。

class的基本含义
class的中文通常翻译为类,它是用户根据自身需求定义的一种复合数据类型。和C++内置的int、double等基础类型不同,class可以包含多种不同类型的成员,既可以有存储数据的变量,也可以有操作这些数据的函数。通过class定义的类型,我们可以创建出对应的实例,也就是对象,每个对象都拥有类定义的成员,但各自的数据可以独立存储。
class的核心特性是封装,它可以将内部实现细节隐藏起来,只对外暴露必要的接口,这样可以减少代码之间的耦合度,降低程序出错的概率。同时class还支持继承和多态,这是实现复杂程序逻辑的重要基础。
class的定义语法
定义class的基本语法格式如下:
class 类名 {
// 访问控制符
public:
// 公有成员:可以被类外部访问
数据类型 成员变量名;
返回类型 成员函数名(参数列表);
private:
// 私有成员:只能被类内部的成员函数访问
数据类型 成员变量名;
返回类型 成员函数名(参数列表);
protected:
// 保护成员:可以被类内部和派生类访问
数据类型 成员变量名;
返回类型 成员函数名(参数列表);
}; // 注意结尾的分号不能省略
其中访问控制符用来限制成员的访问权限,这是实现封装的关键:
- public:公有成员,类外部的代码可以直接访问这些成员
- private:私有成员,只有类内部的成员函数可以访问,外部无法直接调用
- protected:保护成员,除了类内部可以访问,继承该类的派生类也可以访问
如果没有显式声明访问控制符,class中默认的成员访问权限是private,这一点和struct不同,struct的默认访问权限是public。
class的实例化
定义好class之后,我们就可以用它来创建对象,这个过程叫做类的实例化。实例化的对象会拥有类中定义的所有成员,每个对象的数据成员是独立存储的,互不影响。
下面是一个简单的示例,定义一个表示学生的class,然后实例化两个学生对象:
#include <iostream>
#include <string>
using namespace std;
// 定义Student类
class Student {
private:
string name; // 姓名,私有成员
int age; // 年龄,私有成员
public:
// 设置学生信息的成员函数
void setInfo(string n, int a) {
name = n;
age = a;
}
// 打印学生信息的成员函数
void printInfo() {
cout << "姓名:" << name << ",年龄:" << age << endl;
}
};
int main() {
// 实例化两个Student对象
Student stu1;
Student stu2;
// 调用对象的公有成员函数设置信息
stu1.setInfo("张三", 18);
stu2.setInfo("李四", 19);
// 调用对象的公有成员函数打印信息
stu1.printInfo();
stu2.printInfo();
return 0;
}
上面的代码中,Student类有两个私有成员name和age,外部无法直接修改这两个变量,只能通过公有的setInfo和printInfo函数来操作,这就是封装的体现。运行这段代码会输出两个学生的信息,两个对象的数据相互独立。
class的成员函数定义方式
成员函数可以在类内部直接定义,也可以在类内部声明,在类外部定义。如果在类外部定义成员函数,需要使用类名::成员函数名的语法来指定函数属于哪个类。
还是以上面的Student类为例,把成员函数放到类外部定义的写法如下:
#include <iostream>
#include <string>
using namespace std;
class Student {
private:
string name;
int age;
public:
void setInfo(string n, int a); // 类内声明成员函数
void printInfo(); // 类内声明成员函数
};
// 类外部定义setInfo函数
void Student::setInfo(string n, int a) {
name = n;
age = a;
}
// 类外部定义printInfo函数
void Student::printInfo() {
cout << "姓名:" << name << ",年龄:" << age << endl;
}
int main() {
Student stu;
stu.setInfo("王五", 20);
stu.printInfo();
return 0;
}
这种分开定义的方式可以让类的结构更清晰,尤其是当成员函数逻辑比较复杂的时候,适合把声明和定义分开写。
class的构造函数和析构函数
class还有两个特殊的成员函数,分别是构造函数和析构函数。构造函数会在对象实例化的时候自动调用,用来初始化对象的数据成员;析构函数会在对象销毁的时候自动调用,用来做资源释放等清理工作。
构造函数的名称和类名相同,没有返回类型,也不需要写void。析构函数的名称是在类名前加~,同样没有返回类型。
下面是带构造函数和析构函数的Student类示例:
#include <iostream>
#include <string>
using namespace std;
class Student {
private:
string name;
int age;
public:
// 构造函数,带参数
Student(string n, int a) {
name = n;
age = a;
cout << "构造函数被调用,初始化学生:" << name << endl;
}
// 析构函数
~Student() {
cout << "析构函数被调用,销毁学生:" << name << endl;
}
void printInfo() {
cout << "姓名:" << name << ",年龄:" << age << endl;
}
};
int main() {
// 实例化对象时会自动调用构造函数
Student stu("赵六", 21);
stu.printInfo();
// main函数结束时,对象销毁会自动调用析构函数
return 0;
}
运行这段代码可以看到构造函数和析构函数的调用时机,构造函数用于初始化,析构函数用于清理,这两个函数都不需要手动调用,由编译器自动管理。
class的常见使用注意事项
- class定义结尾的分号不能省略,否则会导致编译错误
- 类的成员函数可以访问同类的所有对象的所有成员,包括私有成员
- 如果类中有指针类型的成员,需要注意深拷贝和浅拷贝的问题,必要时需要自定义拷贝构造函数
- 访问控制符可以多次出现,顺序没有限制,通常习惯把public放在前面,方便查看对外接口