25人参与 • 2026-01-23 • C/C++
八股文又来了, 看吧 看一遍你就会了 时间长忘了?那就再看一遍孩子
private、protected、public 是 c++ 封装特性的核心载体,其本质是在编译期限制类成员(变量/函数)在不同作用域下的可见性和访问权限——简单来说,就是规定“哪些地方能使用类的某个成员,哪些地方不能”。掌握这三个关键字的规则,是写出符合工程化规范、高内聚低耦合 c++ 代码的基础。
| 关键字 | 官方定义 | 大白话解释 | 类内访问 | 类外访问(通过对象) | 派生类(子类)访问 |
|---|---|---|---|---|---|
public | 公有的,对外暴露的接口,无访问限制 | 谁都能访问:类自己能用、外部代码能用、子类也能用 | ✅ 允许 | ✅ 允许 | ✅ 允许 |
private | 私有的,仅类内部可见,封装的核心体现 | 只有类自己能用:外部代码不能用、子类也不能用(友元除外) | ✅ 允许 | ❌ 禁止 | ❌ 禁止 |
protected | 受保护的,介于public和private之间,为派生类预留的访问权限 | 类自己能用、子类能用,但外部代码不能用 | ✅ 允许 | ❌ 禁止 | ✅ 允许 |
class 定义类时,默认访问控制是 private(未写关键字的成员均为 private);struct 定义类时,默认访问控制是 public(c++ 对 c 的兼容设计,struct 仅默认权限与 class 不同)。#include <iostream>
using namespace std;
class myclass {
// 未写关键字,class默认private
int default_val = 0;
public:
int pub_val = 10; // 公有成员
void pub_func() {
// 类内:能访问所有成员(public/private/protected)
cout << "类内访问 private_val: " << pri_val << endl;
cout << "类内访问 protected_val: " << pro_val << endl;
cout << "类内访问 default_val: " << default_val << endl;
}
private:
int pri_val = 20; // 私有成员
void pri_func() { cout << "私有函数" << endl; }
protected:
int pro_val = 30; // 受保护成员
void pro_func() { cout << "受保护函数" << endl; }
};
// 派生类(子类)
class derived : public myclass {
public:
void derived_func() {
// 派生类:能访问基类的public/protected,不能访问private
cout << "派生类访问 pub_val: " << pub_val << endl; // ✅ 允许
cout << "派生类访问 pro_val: " << pro_val << endl; // ✅ 允许
// cout << "派生类访问 pri_val: " << pri_val << endl; // ❌ 禁止:private不可访问
pro_func(); // ✅ 允许调用protected函数
// pri_func(); // ❌ 禁止调用private函数
}
};
int main() {
myclass obj;
// 类外:仅能访问public成员
cout << "类外访问 pub_val: " << obj.pub_val << endl; // ✅ 允许
// cout << "类外访问 pro_val: " << obj.pro_val << endl; // ❌ 禁止:protected不可访问
// cout << "类外访问 pri_val: " << obj.pri_val << endl; // ❌ 禁止:private不可访问
obj.pub_func(); // ✅ 允许调用public函数
// obj.pro_func(); // ❌ 禁止调用protected函数
// obj.pri_func(); // ❌ 禁止调用private函数
derived d_obj;
d_obj.derived_func(); // ✅ 派生类内部逻辑正常执行
return 0;
}访问控制是“类级别”的限制,而非“对象级别”——同一个类的不同对象,可互相访问对方的 private/protected 成员(编译期认为属于“同一类的内部”):
#include <iostream>
using namespace std;
class myclass {
private:
int m_val = 10;
public:
// 访问同类型另一个对象的private成员
void accessanotherobj(myclass& other) {
cout << "访问另一个对象的private成员:" << other.m_val << endl; // ✅ 允许
other.m_val = 20; // ✅ 可修改
}
int getval() const { return m_val; }
};
int main() {
myclass a, b;
a.accessanotherobj(b); // 输出:访问另一个对象的private成员:10
cout << "修改后b的val:" << b.getval() << endl; // 输出:20
return 0;
}派生类继承基类时,继承方式(public/protected/private) 会修改“基类成员在派生类中的访问权限”,核心铁律:
派生类对基类成员的访问权限 = 「基类成员自身的访问权限」和「继承方式」中更严格的那个。
| 基类成员访问权限 | public继承(最常用) | protected继承 | private继承 |
|---|---|---|---|
| public | public(不变) | protected | private |
| protected | protected(不变) | protected | private |
| private | 不可访问(不变) | 不可访问 | 不可访问 |
#include <iostream>
using namespace std;
// 基类
class base {
public:
int pub_val = 1;
protected:
int pro_val = 2;
private:
int pri_val = 3;
};
// 1. public继承(开发中99%的场景,推荐)
class derivedpub : public base {
public:
void show() {
cout << "pub_val: " << pub_val << endl; // ✅ public → public
cout << "pro_val: " << pro_val << endl; // ✅ protected → protected
// cout << pri_val << endl; // ❌ 始终不可访问
}
};
// 2. protected继承
class derivedpro : protected base {
public:
void show() {
cout << "pub_val: " << pub_val << endl; // ✅ public → protected
cout << "pro_val: " << pro_val << endl; // ✅ protected → protected
}
};
// 3. private继承
class derivedpri : private base {
public:
void show() {
cout << "pub_val: " << pub_val << endl; // ✅ public → private
cout << "pro_val: " << pro_val << endl; // ✅ protected → private
}
};
int main() {
derivedpub d_pub;
cout << d_pub.pub_val << endl; // ✅ public继承后,基类public仍为public,类外可访问
// cout << d_pub.pro_val << endl; // ❌ protected,类外不可访问
derivedpro d_pro;
// cout << d_pro.pub_val << endl; // ❌ public继承后变为protected,类外不可访问
derivedpri d_pri;
// cout << d_pri.pub_val << endl; // ❌ public继承后变为private,类外不可访问
return 0;
}多层继承中,基类成员权限会随继承链“层层收紧”(仅会更严格,不会放宽):
#include <iostream>
using namespace std;
// 顶层基类
class a {
public:
int pub_a = 1;
protected:
int pro_a = 2;
};
// 第二层:b public继承a
class b : public a {
public:
void showb() {
cout << "b中访问a的pub_a:" << pub_a << endl; // ✅ public→public
cout << "b中访问a的pro_a:" << pro_a << endl; // ✅ protected→protected
}
};
// 第三层:c protected继承b
class c : protected b {
public:
void showc() {
// a的pub_a:a→b(public)→c(protected)→ 最终c中是protected
cout << "c中访问a的pub_a:" << pub_a << endl; // ✅ 允许(c内可访问protected)
// a的pro_a:a→b(protected)→c(protected)→ 最终c中是protected
cout << "c中访问a的pro_a:" << pro_a << endl; // ✅ 允许
}
};
// 第四层:d private继承c
class d : private c {
public:
void showd() {
// a的pub_a:经过三层继承后变为private
cout << "d中访问a的pub_a:" << pub_a << endl; // ✅ d内可访问private
}
};
int main() {
c c;
// cout << c.pub_a << endl; // ❌ c中pub_a是protected,类外不可访问
d d;
// cout << d.pub_a << endl; // ❌ d中pub_a是private,类外不可访问
return 0;
}static 仅改变成员的“存储方式”(属于类而非对象),访问控制规则与普通成员完全一致:
#include <iostream>
using namespace std;
class myclass {
private:
static int s_pri_val; // 静态私有成员
protected:
static int s_pro_val; // 静态受保护成员
public:
static int s_pub_val; // 静态公有成员
static void showstatic() {
// 类内可访问所有静态成员
cout << "静态私有:" << s_pri_val << endl;
cout << "静态受保护:" << s_pro_val << endl;
}
};
// 静态成员必须类外初始化
int myclass::s_pri_val = 10;
int myclass::s_pro_val = 20;
int myclass::s_pub_val = 30;
// 派生类
class derived : public myclass {
public:
static void showderivedstatic() {
// 派生类可访问基类的static protected/public
cout << "派生类访问静态受保护:" << s_pro_val << endl; // ✅
cout << "派生类访问静态公有:" << s_pub_val << endl; // ✅
// cout << s_pri_val << endl; // ❌ 静态私有仍不可访问
}
};
int main() {
// 类外仅能访问静态公有成员
cout << myclass::s_pub_val << endl; // ✅ 30
// cout << myclass::s_pro_val << endl; // ❌ 静态受保护,类外不可访问
// cout << myclass::s_pri_val << endl; // ❌ 静态私有,类外不可访问
derived::showderivedstatic(); // ✅ 派生类内可访问静态受保护
return 0;
}protected 允许“子类访问自己的基类成员”,但禁止子类访问其他子类对象的基类 protected 成员:
#include <iostream>
using namespace std;
class base {
protected:
int m_val = 10;
};
class deriveda : public base {
public:
// 错误场景:deriveda试图访问derivedb对象的protected成员
void accessderivedb(derivedb& b) {
// cout << b.m_val << endl; // ❌ 禁止:不能访问其他子类对象的protected
}
// 正确场景:访问自己的protected成员
void accessself() {
cout << m_val << endl; // ✅ 允许
}
};
class derivedb : public base {}; // 另一个子类
int main() {
deriveda a;
derivedb b;
a.accessself(); // ✅ 输出10
// a.accessderivedb(b); // ❌ 编译报错
return 0;
}friend 是 c++ 中唯一能突破 private/protected 访问限制的语法,核心是“显式授权”——只有被类主动声明为友元的函数/类,才能访问其私有/受保护成员。友元按授权粒度从粗到细分为以下三种形式:
友元函数是最基础的友元形式,授权单个普通函数访问类的私有/受保护成员,适用于“仅需一个外部函数访问类内部数据”的场景(如运算符重载、简单的外部工具函数)。
#include <iostream>
using namespace std;
class myclass {
private:
int pri_val = 100;
// 声明友元函数:仅授权showprivate函数访问当前类的私有成员
friend void showprivate(myclass& obj);
};
// 友元函数:可以直接访问myclass的private成员(无需通过public接口)
void showprivate(myclass& obj) {
cout << "访问private成员: " << obj.pri_val << endl; // ✅ 允许
}
int main() {
myclass obj;
showprivate(obj); // 输出:访问private成员: 100
return 0;
}核心总结:
public/private/protected 任意区域,效果完全一致;友元类是“批量授权”形式,授权另一个类的所有成员函数(无论 public/private/protected)访问当前类的私有/受保护成员,适用于“两个类高度耦合且需要深度协作”的场景(如容器类和其迭代器类)。
#include <iostream>
using namespace std;
class a {
// 声明b为友元类:b的所有成员函数都能访问a的私有/受保护成员
friend class b;
private:
int m_val = 100;
};
class b {
public:
// b的公有成员函数:访问a的私有成员
void accessa(a& a) {
cout << a.m_val << endl; // ✅ 允许
}
private:
// b的私有成员函数:同样能访问a的私有成员(友元类的所有成员函数都有权限)
void privateaccessa(a& a) {
a.m_val = 200; // ✅ 允许修改
}
};
int main() {
a a;
b b;
b.accessa(a); // 输出:100
return 0;
}核心总结:
友元成员函数是“精准授权”形式,仅授权另一个类的某个特定成员函数访问当前类的私有/受保护成员,是兼顾“协作需求”和“封装性”的最优友元形式。
#include <iostream>
using namespace std;
// 前置声明:必须先声明a,才能在b的成员函数参数中使用a的引用
class a;
class b {
public:
// 先声明需要授权的成员函数(仅该函数需要访问a的私有成员)
void onlythisfunccanaccessa(a& a);
};
class a {
// 仅授权b类的onlythisfunccanaccessa成员函数访问当前类的私有成员
friend void b::onlythisfunccanaccessa(a& a);
private:
int m_val = 500;
};
// 实现授权的成员函数:可直接访问a的私有成员
void b::onlythisfunccanaccessa(a& a) {
cout << a.m_val << endl; // ✅ 允许
}
int main() {
a a;
b b;
b.onlythisfunccanaccessa(a); // 输出:500
return 0;
}核心总结:
友元关系的核心规则不受授权形式影响,需牢记以下三点:
| 关键字 | 核心应用场景 | 示例 |
|---|---|---|
public | 对外提供的「接口」(稳定、不轻易修改) | 业务方法(如 calculate())、get/set函数(如 getname()/setname()) |
private | 类的「内部实现细节」(隐藏,避免外部篡改) | 成员变量(如 m_name)、内部辅助函数(如 checkvalid()) |
protected | 基类中需要给「派生类复用」,但不希望外部访问的成员 | 基类的通用属性(如 m_id)、通用方法(如 initdata()) |
反模式1:成员变量设为 public
// 错误
class student {
public:
int m_age; // 外部可直接赋值 m_age = -5,数据完全不安全
};
// 正确
class student {
private:
int m_age;
public:
void setage(int age) {
if (age >= 0 && age <= 120) m_age = age; // 带校验的写接口
}
int getage() const { return m_age; } // 只读接口
};反模式2:为方便将 protected 改为 public
// 错误
class base {
public:
int m_id; // 本应给子类复用的成员,被外部随意修改
};
// 正确
class base {
protected:
int m_id;
public:
int getid() const { return m_id; } // 仅暴露只读接口
};反模式3:过度使用友元,破坏封装
// 错误:授权多个类/函数,封装形同虚设
class a {
friend class b;
friend class c;
friend void func1();
friend void func2();
private:
int m_data;
};
// 正确:仅授权必要的函数/类
class a {
friend void onlynecessaryfunc(a& a);
private:
int m_data;
};protected 是“派生类的 private”→ 派生类之间不能访问对方的 protected 成员;static 会改变访问控制 → static private 仍仅类内可访问,static 不影响权限;private 绝对不可访问 → 友元是合法途径,指针强制转换是不规范黑科技,严禁使用;struct 没有访问控制 → struct 只是默认权限为 public,同样支持 private/protected。class 和 struct 的访问控制默认值有什么区别?class 默认访问控制是 private,struct 默认是 public(c++ 对 c 的兼容设计,struct 保留 c 的特性);protected 和 private 的核心区别是什么?protected 允许派生类访问,private 不允许;类外两者都不可访问;public 成员的公有属性(类外可访问),private 继承会把基类所有可访问成员变为 private(仅派生类内可访问);开发中优先用 public 继承;private/protected 成员,是访问控制的合法例外。问:为什么私有虚函数能被派生类重写?
#include <iostream>
using namespace std;
class base {
private:
virtual void func() { cout << "base::func" << endl; }
public:
void callfunc() { func(); } // 公有接口调用私有虚函数
};
class derived : public base {
private:
void func() override { cout << "derived::func" << endl; }
};
int main() {
base* ptr = new derived();
ptr->callfunc(); // 输出:derived::func
delete ptr;
return 0;
}答:访问控制(private)和多态(虚函数)是两个独立的机制:
public(类内/外/派生类)、private(仅类内+友元)、protected(类内+派生类);protected 仅允许子类访问自身的基类成员;public 做接口、private 藏实现、protected 给子类复用,严禁 public 成员变量和过度友元。到此这篇关于c++ private、protected、public从入门到精通实例解析的文章就介绍到这了,更多相关c++ private、protected、public内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
您想发表意见!!点此发布评论
版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。
发表评论