zensyra
发布于 2025-11-06 / 2 阅读
0

C++访问控制

在 C++ 中public、protected​、private​是 访问控制修饰符(Access Specifiers),用于限制类(class​/struct​)成员(属性、方法)的访问权限 —— 核心目的是实现封装性(隐藏内部实现细节,仅暴露必要接口),同时支持继承体系中的权限控制。

访问权限的核心规则:从类外部能否直接访问成员、子类能否访问父类的成员。

1. public(公有访问)

  • 含义:类的公有成员是 “对外暴露的接口”,不受访问限制。

  • 访问范围:

    • 类的外部代码(如 main​ 函数、其他普通函数)可以直接访问;

    • 类的成员函数(自身内部)可以访问;

    • 类的子类(派生类)可以直接访问(无论哪种继承方式)。

  • 使用场景:暴露给外部的接口(如构造函数、对外提供的功能方法、必要的公开属性)。

示例:

class Person {
public:  // 公有成员
    std::string name;  // 公有属性
    void sayHello() {  // 公有方法
        std::cout << "Hello, " << name << std::endl;
    }
};

// 类外部访问 public 成员(允许)
int main() {
    Person p;
    p.name = "Alice";  // 直接访问公有属性
    p.sayHello();      // 直接调用公有方法
    return 0;
}

2. private(私有访问)

  • 含义:类的私有成员是 “内部实现细节”,仅对类自身可见,完全隐藏对外。

  • 访问范围:

    • 仅允许类的自身成员函数(包括友元函数 / 友元类)访问;

    • 类的外部代码无法直接访问(编译报错);

    • 类的子类无法直接访问(即使是公有继承,子类也不能直接用父类的 private 成员)。

  • 使用场景:隐藏内部状态或辅助方法(如内部缓存、私有工具函数),避免外部误修改。

示例:

class BankAccount {
private:  // 私有成员(内部状态,对外隐藏)
    double balance;  // 账户余额(不允许外部直接修改)

public:  // 公有接口(控制访问)
    void deposit(double money) {  // 存款(仅通过该接口修改余额)
        if (money > 0) balance += money;
    }
    double getBalance() {  // 查询余额(仅暴露读取接口)
        return balance;
    }
};

int main() {
    BankAccount acc;
    // acc.balance = 1000;  // 错误:private 成员,外部无法直接访问
    acc.deposit(1000);      // 正确:通过公有接口修改
    std::cout << acc.getBalance() << std::endl;  // 正确:通过公有接口读取
    return 0;
}

3. protected(受保护访问)

  • 含义:类的受保护成员是 “仅对自身和子类可见的内部成员”,介于 public​ 和 private​ 之间。

  • 访问范围:

    • 允许类的自身成员函数访问;

    • 允许类的子类(派生类)的成员函数直接访问(无论哪种继承方式);

    • 类的外部代码无法直接访问(编译报错)。

  • 使用场景:父类希望子类继承并使用,但不希望外部代码访问的成员(如父类的辅助方法、子类需要复用的属性)。

示例:

class Animal {
protected:  // 受保护成员(子类可访问,外部不可)
    std::string species;  // 物种(子类需要用到,但外部无需知道)

public:
    Animal(std::string s) : species(s) {}
};

// 子类 Dog 继承 Animal
class Dog : public Animal {
public:
    Dog() : Animal("Dog") {}
    void showSpecies() {
        // 正确:子类成员函数可直接访问父类的 protected 成员
        std::cout << "I am a " << species << std::endl;
    }
};

int main() {
    Dog dog;
    dog.showSpecies();  // 正确:通过子类公有接口间接访问
    // std::cout << dog.species << std::endl;  // 错误:外部无法访问 protected 成员
    return 0;
}

关键补充:继承中的权限变化

当子类继承父类时(public​/protected​/private​ 继承),父类成员在子类中的 “可见性” 会有变化,但核心规则不变:子类永远无法访问父类的 private 成员。

父类成员权限

public 继承(最常用)

protected 继承

private 继承

public

子类中仍为 public

子类中变为 protected

子类中变为 private

protected

子类中仍为 protected

子类中仍为 protected

子类中变为 private

private

子类中不可访问

子类中不可访问

子类中不可访问

注:struct​ 与 class​ 的默认访问权限不同:

  • ​class​:默认成员权限为 private​,默认继承方式为 private​;

  • ​struct​:默认成员权限为 public​,默认继承方式为 public​(兼容性设计,与 C 语言一致)。

总结:核心区别表

修饰符

类内部

子类内部

类外部

核心用途

public

暴露对外接口(如构造函数、功能方法)

protected

父类与子类共享的内部成员

private

类自身的隐藏实现细节

一句话记忆:public 对外,private 对内,protected 父对子开放、对外封闭。

end