C++ 类访问修饰符

C++ 类 & 对象 C++ 类 & 对象

在 C++ 面向对象编程(OOP)中,数据封装(Encapsulation) 是核心概念之一。简单来说,就是把数据"藏"起来,只开放必要的接口给外界使用,以保证数据的安全。

为了控制谁能看到这些数据,C++ 提供了三个关键字,称为访问修饰符

  • public (公有)
  • private (私有)
  • protected (受保护)
class Base { public: //公有成员 protected: // 受保护成员 private: // 私有成员 };

为了方便理解,我们可以把一个类(Class)想象成你的家

修饰符 现实类比 谁可以访问? 典型用途
public 客厅/大门 所有人(类内部、子类、外部代码) 对外提供的接口函数(API)。
protected 卧室 你和你的孩子(类内部、子类) 仅限家族内部(继承体系)使用的数据。
private 保险箱 只有你自己(仅限本类内部) 核心数据、不想被随意修改的变量。

注意:如果不写任何修饰符,C++ 类成员默认是 private(私有) 的。

公有(public)成员

公有成员在程序中任何地方都能访问,无需通过成员函数读写,示例如下:

实例

#include <iostream> using namespace std; class Line { public: double length; void setLength( double len ); double getLength( void ); }; // 成员函数定义 double Line::getLength(void) { return length ; } void Line::setLength( double len ) { length = len; } // 程序的主函数 int main( ) { Line line; // 设置长度 line.setLength(6.0); cout << "Length of line : " << line.getLength() <<endl; // 不使用成员函数设置长度 line.length = 10.0; // OK: 因为 length 是公有的 cout << "Length of line : " << line.length <<endl; return 0; }

当上面的代码被编译和执行时,它会产生下列结果:

Length of line : 6
Length of line : 10

私有(private)成员

私有成员对类外完全封闭,外部代码无法读取、修改或调用,派生类同样无权直接访问。只有类自身的成员函数与被授予友元权限的实体能够操作这些内容。

类中若未使用任何访问说明符,成员默认为私有。如下例所示,width 自动落入私有区域,表明未明确标注的成员均按私有处理:

实例

class Box { double width; public: double length; void setWidth( double wid ); double getWidth( void ); };

实际操作中,我们一般会在私有区域定义数据,在公有区域定义相关的函数,以便在类的外部也可以调用这些函数,如下所示:

实例

#include <iostream> using namespace std; class Box { public: double length; void setWidth( double wid ); double getWidth( void ); private: double width; }; // 成员函数定义 double Box::getWidth(void) { return width ; } void Box::setWidth( double wid ) { width = wid; } // 程序的主函数 int main( ) { Box box; // 不使用成员函数设置长度 box.length = 10.0; // OK: 因为 length 是公有的 cout << "Length of box : " << box.length <<endl; // 不使用成员函数设置宽度 // box.width = 10.0; // Error: 因为 width 是私有的 box.setWidth(10.0); // 使用成员函数设置宽度 cout << "Width of box : " << box.getWidth() <<endl; return 0; }

当上面的代码被编译和执行时,它会产生下列结果:

Length of box : 10
Width of box : 10

protected(受保护)成员

protected 的存在主要是为了继承

  • 如果没有继承,它和 private 一样(外人不可见)。
  • 如果有继承,子类(派生类)可以访问父类的 protected 成员,但不能访问 private 成员。

在下一个章节中,您将学习到派生类和继承的知识。现在您可以看到下面的实例中,我们从父类 Box 派生了一个子类 smallBox

下面的实例与前面的实例类似,在这里 width 成员可被派生类 smallBox 的任何成员函数访问。

实例

#include <iostream> using namespace std; class Box { protected: double width; }; class SmallBox:Box // SmallBox 是派生类 { public: void setSmallWidth( double wid ); double getSmallWidth( void ); }; // 子类的成员函数 double SmallBox::getSmallWidth(void) { return width ; } void SmallBox::setSmallWidth( double wid ) { width = wid; } // 程序的主函数 int main( ) { SmallBox box; // 使用成员函数设置宽度 box.setSmallWidth(5.0); cout << "Width of box : "<< box.getSmallWidth() << endl; return 0; }

当上面的代码被编译和执行时,它会产生下列结果:

Width of box : 5

继承中的访问权限变化

当你定义一个子类时(如 class B : public A),冒号后面的 public 也是一种访问修饰符,它决定了父类的成员在子类中"表现"成什么样

这看起来很复杂,但只需要记住这个降级原则

继承方式决定了父类成员在子类中的最高权限。
如果继承方式比成员原本的权限更严格,成员的权限就会被"降级"到继承方式的级别。

权限变化表

父类成员原权限 public 继承 (最常用) protected 继承 private 继承
public 保持 public 降级为 protected 降级为 private
protected 保持 protected 保持 protected 降级为 private
private 不可访问 不可访问 不可访问

注:不可访问指子类代码无法直接使用该变量,但变量依然存在于内存中。

综合演示代码

为了清晰展示,我们将变量重命名为 pub_var (公有), pro_var (受保护), pri_var (私有)。

实例

#include <iostream>
using namespace std;

class Parent {
public:
    int pub_var;
protected:
    int pro_var;
private:
    int pri_var; // 只有 Parent 自己能动

public:
    Parent() { pub_var = 1; pro_var = 2; pri_var = 3; }
};

// 1. 公有继承(Public Inheritance)- 最常见,原汁原味
class ChildA : public Parent {
public:
    void test() {
        cout << pub_var << endl; // OK
        cout << pro_var << endl; // OK
        // cout << pri_var << endl; // 错误!父类私有成员不可见
    }
};

// 2. 受保护继承(Protected Inheritance)- 大家都变成了受保护
class ChildB : protected Parent {
public:
    void test() {
        cout << pub_var << endl; // OK,但在 ChildB 看来,它是 protected
        cout << pro_var << endl; // OK
    }
};

// 3. 私有继承(Private Inheritance)- 大家都变成了私有
class ChildC : private Parent {
public:
    void test() {
        cout << pub_var << endl; // OK,但在 ChildC 看来,它是 private
        cout << pro_var << endl; // OK,但在 ChildC 看来,它是 private
    }
};

int main() {
    ChildA a;
    cout << a.pub_var << endl; // OK,外部可以访问
    // cout << a.pro_var << endl; // 错误,外部不可访问 protected

    ChildB b;
    // cout << b.pub_var << endl; // 错误!因为是 protected 继承,pub_var 在外部变成了 protected

    ChildC c;
    // cout << c.pub_var << endl; // 错误!因为是 private 继承,pub_var 在外部变成了 private

    return 0;
}

总结

  • Public: 谁都能用。做接口(API)用。
  • Private: 只有自己能用。存数据用(默认安全选项)。
  • Protected: 只有家族(继承链)能用。给子类留后门用。

继承:

  • Public 继承:父类的属性保持不变(最常用)。
  • Private/Protected 继承:会收紧父类成员的权限,通常用于特殊的实现场景。

C++ 类 & 对象 C++ 类 & 对象