大话C++:第11篇 类的定义与封装
1 类的定义
在C++中,类的定义通常使用class
关键字开始,后面紧跟类的名称。类可以包含数据成员(变量)和成员函数(方法)。
在C++中,类可以更加详细地展开,包括数据成员(变量)的声明、成员函数的声明与定义、构造函数、析构函数、内联成员函数、静态成员、友元函数等。类定义的语法格式:
// ClassName类名
class ClassName
{
public:
// 公共构造函数
ClassName(); // 默认构造函数
ClassName(const ClassName& other); // 拷贝构造函数
~ClassName(); // 析构函数
// 公共成员函数(包括内联函数)
void publicFunction();
void anotherPublicFunction() const; // const成员函数
static void staticPublicFunction(); // 静态成员函数
// 公共成员变量(通常不推荐,因为破坏了封装性)
int publicVariable;
// 友元函数和友元类
friend void friendFunction(ClassName& obj);
friend class FriendClass;
protected:
// 受保护成员函数
void protectedFunction();
// 受保护成员变量
int protectedVariable;
private:
// 私有成员函数
void privateFunction();
// 私有成员变量
int privateVariable;
// 私有静态成员变量
static int privateStaticVariable;
// 私有静态成员函数
static void privateStaticFunction();
// 类内定义成员函数(内联函数)
inline void inlineFunction() {
// 函数体
}
// 类的嵌套类
class NestedClass {
// NestedClass 的定义
};
};
其中,
-
构造函数和析构函数用于对象的初始化和清理。
-
成员函数可以是公共的、受保护的或私有的。
-
静态成员(函数和变量)属于类本身,而不是类的任何特定对象。
-
友元函数和友元类可以访问类的私有和保护成员。
-
内联函数通过在调用点插入函数体的复制品来提高执行速度,适合函数体简短且调用频繁的情况。
-
嵌套类是在另一个类内部定义的类。
类的定义通常放在头文件中,类的实现放在源码文件cpp。例如,学生的定义与实现
-
student.h学生类的定义
// student.h
#ifndef __STUDENT_H__
#define __STUDENT_H__
#include <string>
class Student
{
public:
// 构造函数
Student(const std::string& name, int age, int num);
// 析构函数
~Student();
// 公共成员函数
void DisplayInfo() const;
// 获取成员变量的函数
// 获取姓名
inline std::string GetName() const;
// 获取年龄
inline int GetAge() const;
// 获取学号
inline int GetNum() const;
// 设置成员变量的函数
// 设置姓名
inline void SetName(const std::string& name);
// 设置年龄
inline void SetAge(const int age);
// 设置学号
inline void SetNum(const int num);
private:
// 私有成员变量
std::string _name; // 姓名
int _age; // 年龄
int _num; // 学号
};
#endif // __STUDENT_H__
-
student.cpp学生类的实现
// student.cpp
#include "student.h"
#include <iostream>
// 构造函数
Student::Student(const std::string& name, int age, int num)
: _name(name),
_age(age),
_num(num)
{
std::cout << "Student构造函数" << std::endl;
}
// 析构函数(在这个简单的例子中,析构函数是空的)
Student::~Student()
{
std::cout << "Student析构函数" << std::endl;
}
// 显示学生信息
void Student::DisplayInfo() const
{
std::cout << "该学生姓名:" << _name
<< ",年龄:" << _age
<< ",学号:" << _num
<< std::endl;
}
// 获取学生姓名
std::string Student::GetName() const
{
return _name;
}
// 获取年龄
int Student::GetAge() const
{
return _age;
}
// 获取学号
int Student::GetNum() const
{
return _num;
}
// 设置姓名
void Student::SetName(const std::string& name)
{
_name = name;
}
// 设置年龄
void Student::SetAge(const int age)
{
_age = age;
}
// 设置学号
void Student::SetNum(const int num)
{
_num = num;
}
-
main.cpp学生对象的定义及使用
// main.cpp
#include <iostream>
#include "student.h"
int main()
{
// 创建学生对象
Student student("Jack", 25);
// 调用成员函数
student.DisplayInfo();
std::cout << "该学生对象的名字: " << student.GetName() << std::endl;
// 修改学生年龄
student.SetAge(22);
// 再次调用成员函数
student.DisplayInfo();
return 0;
}
2 类的封装
C++ 类的封装是面向对象编程中的一个核心概念,它指的是将数据(成员变量)和行为(成员函数)结合在一起的机制,并隐藏内部实现细节,只暴露出一个可以被外界访问和使用的接口。封装可以提高安全性和易于维护,因为它限制了对类内部数据的直接访问,只允许通过类提供的成员函数来操作数据。
为了实现封装,C++提供了访问修饰符(public
、private
、protected
)来控制类成员的访问权限。访问修饰符对类、派生类及对象具有不同的访问权限,如下表所示:
访问修饰符 | 类内部 | 派生类内部 | 对象(外部) | 示例 |
---|---|---|---|---|
public | 可访问 | 可访问 | 可访问 | 成员在类的外部和内部都可以被访问。 |
private | 可访问 | 不可访问 | 不可访问 | 成员只能在类的内部被访问,对象和派生类都无法直接访问 |
protected | 可访问 | 可访问 | 不可访问 | 成员在类的内部和派生类中可以被访问,但对象无法直接访问 |
#include <iostream>
class Person
{
public:
void SetName(const std::string& name) { // 公有成员函数
_name = name;
}
std::string GetName() const
{
// 公有成员函数
return _name;
}
protected:
// 受保护成员函数
void SetAge(int age)
{
_age = age;
}
protected:
// 受保护成员变量
int _age;
private:
// 私有成员变量
std::string _name;
};
int main()
{
Person person;
// 对象无法直接访问私有成员
// person._name = "Alice";
// 对象可以访问公有成员函数
person.SetName("Jack");
std::cout << person.GetName() << std::endl;
// 对象无法直接访问受保护成员
// person._age = 10; // 错误:受保护成员无法访问
return 0;
}
3 类的访问修饰符
在C++中,类的访问修饰符主要用于控制类成员(包括数据成员和成员函数)的访问权限。这些修饰符主要有四种:public
、protected
、private
和默认的default
。其中,
-
public(公共访问修饰符):
-
访问权限:最高级别的访问权限。
-
作用:允许类的任何对象以及任何其他代码访问该类的成员(无论是数据成员还是成员函数)。
-
使用场景:通常用于提供类的外部接口,即允许外部代码调用的成员函数或访问的数据成员。
-
-
protected(受保护的访问修饰符):
-
访问权限:次高级别的访问权限。
-
作用:允许类的对象、派生类(子类)以及类的内部代码访问该类的成员。
-
使用场景:通常用于实现继承时,在基类中定义一些需要被子类访问但不需要被外界访问的成员。
-
-
private(私有的访问修饰符):
-
访问权限:最低级别的访问权限。
-
作用:只允许类的内部代码访问该类的成员。
-
使用场景:通常用于隐藏类的内部实现细节,确保数据的封装性。
-
-
default(默认访问修饰符):
-
访问权限:包(package)级别的访问权限。
-
作用:允许同一包(package)中的其他类访问该类的成员,但不允许包外的类访问。
-
表格形式总结一下,详见下表:
访问修饰符 | 访问权限 | 类内部 | 派生类内部 | 类的对象 | 同包其他类 | 说明 |
---|---|---|---|---|---|---|
public | 公有 | 可访问 | 可访问 | 可访问 | 可访问 | 允许外部访问 |
protected | 受保护 | 可访问 | 可访问 | 不可访问 | 不可访问 | 允许派生类访问 |
private | 私有 | 可访问 | 不可访问 | 不可访问 | 不可访问 | 仅允许类内部访问 |
注意:在C++中,没有明确的default
关键字来表示包私有访问,这里的default
仅用于类比,代表类内部和同一包内其他类可以访问,但对象和包外类无法访问。在C++中,如果一个成员没有被显式声明为public
、protected
或private
,那么它的访问级别就是private
。