Menu
CoddyTech

C++ 中的访问控制符

本课属于 Coddy C++ 学习旅程的“面向对象编程”单元。第 34 课,共 104 课。

C++ 提供了三种访问修饰符,用于控制谁可以访问类成员:public、protected 和 private。它们构成了封装的基础。

class Account {
public:
    std::string ownerName;      // 可以从任何地方访问
    
protected:
    double interestRate;        // 可以在此类及其派生类中访问
    
private:
    double balance;             // 只能在此类内部访问
};

公有成员可以从任何地方访问,包括类内部、派生类以及外部代码。私有成员的限制最严格,只能在类本身内部访问。受保护介于两者之间:对外部代码来说,它的作用类似于私有成员,但派生类可以访问这些成员。

class Account {
private:
    double balance;
    
public:
    Account() : balance(0) {}
    
    void deposit(double amount) {
        balance += amount;    // 可以,在类内部
    }
};

int main() {
    Account acc;
    acc.deposit(100);         // 可以,deposit 是公有的
    // acc.balance = 500;     // 错误:balance 是私有的
}

默认情况下,如果没有指定访问修饰符,类中的所有成员都是私有的。这样可以鼓励你明确决定要公开哪些内容。通常的做法是将数据成员设为私有,并提供公有方法,以便安全地与它们交互。

challenge icon

挑战

简单

让我们构建一个简单的员工管理系统,演示访问修饰符如何控制谁能访问哪些内容。你将创建一个类,其中一些数据完全私有,一些数据可供可能的派生类访问,还有一些数据对所有人开放。

你将创建两个文件来组织代码:

  • Employee.h:定义一个使用全部三种访问修饰符来恰当保护数据的 Employee 类:
    • Public:员工的 name(字符串)。可以从任何位置访问
    • Protected:员工的 department(字符串):可在类内部以及派生类中访问,但不能从类外部访问
    • Private:员工的 salary(double):只能在类内部访问
    • 一个构造函数,接收 name、department 和 salary,并初始化这三个成员
    • 一个公有方法 getSalary(),返回私有的 salary 值
    • 一个公有方法 getDepartment(),返回受保护的 department 值
    • 一个公有方法 giveRaise(double amount),按给定金额增加 salary(仅当 amount 为正数时)
    • 一个公有方法 displayInfo(),按以下格式打印员工信息:"Name: <name>, Department: <department>, Salary: $<salary>"
  • main.cpp:通过与一个 Employee 对象交互,演示访问修饰符的作用。从输入中读取员工的姓名、部门和工资(分为三行),然后:
    • 使用输入值创建一个 Employee
    • 直接访问公有成员,打印员工姓名:"Direct access - Name: <name>"
    • 使用 getter 打印部门:"Via getter - Department: <department>"
    • 使用 getter 打印工资:"Via getter - Salary: $<salary>"
    • 给员工加薪 5000.0
    • 打印 "After raise:"
    • 调用 displayInfo() 显示更新后的信息

使用 std::fixed 和 <iomanip> 中的 std::setprecision(2),将所有工资值格式化为两位小数。使用 std::stod() 将工资输入从字符串转换为 double。

这里的关键在于,虽然你可以在 main 中直接访问 name,但不能直接访问 department 或 salary。你必须使用公有 getter 方法。这就是封装的实际应用:类控制着如何访问和修改其中的数据。

亲手试试

#include <iostream>
#include <string>
#include <iomanip>
#include "Employee.h"

using namespace std;

int main() {
    // 读取输入
    string name;
    string department;
    string salaryStr;
    
    getline(cin, name);
    getline(cin, department);
    getline(cin, salaryStr);
    double salary = stod(salaryStr);
    
    // 设置薪资输出的精度
    cout << fixed << setprecision(2);
    
    // TODO:使用输入值创建一个 Employee 对象
    
    // TODO:直接访问公有成员,输出员工姓名
    // 格式:"Direct access - Name: <name>"
    
    // TODO:使用 getter 方法输出部门
    // 格式:"Via getter - Department: <department>"
    
    // TODO:使用 getter 方法输出薪资
    // 格式:"Via getter - Salary: $<salary>"
    
    // TODO:给员工加薪 5000.0
    
    // TODO:输出 "After raise:"
    
    // TODO:调用 displayInfo() 显示更新后的信息
    
    return 0;
}
quiz icon自我测试

这节课包含一个小测验。开始学习即可作答,并记录你的进度。

面向对象编程中的所有课

自己练习: C++ 在线编译器