详解C++中的公有继承与私有继承访问规则

陆景行
陆景行
发布时间:2026-10-13| 6人浏览过
原创

在C++面向对象编程中,继承是实现代码复用和多态的核心机制。根据声明方式的不同,继承关系主要分为公有继承(public)和私有继承(private)。理解两者对基类成员(public、protected、private)在派生类中访问属性的影响,是编写正确C++程序的关键。

什么是私有继承及其访问规则

当在派生类声明中将基类的继承方式指定为 private 时,称为私有继承。由此建立的派生类称为私有派生类(private derived class)。

私有继承最显著的特征是“隐藏”。其基类(public base class)的所有非私有成员在派生类中均被视为 private。具体访问属性变化如下:



简而言之:

  • 基类 public/protected 成员:在派生类中变成 private。这意味着派生类内部可以访问,但派生类外部(包括通过派生类对象)无法访问。
  • 基类 private 成员:在派生类中成为不可访问的成员。仅能通过基类的成员函数间接访问。

由于私有继承将基类的接口彻底隐藏,下一层的派生类也无法访问其任何成员,因此在不需要继续向下继承的场景中,为了隐蔽功能逻辑时才会使用。但由于其访问限制较多,一般日常编程中使用较少。

第1步:定义私有继承类并测试访问权限

假设我们有一个基类 Student,现在以私有方式创建一个派生类 Student1,观察不同作用域的访问情况。

class Student1: private Student // 用私有继承方式声明派生类Student1
{
public:
  void display_1() { 
   // 以下引用均为派生类内的私有成员,访问正确
   cout<<"age: "<<age<<endl; 
   cout<<"address: "<<addr<<endl;
  }
private:
  int age;
  string addr;
};

第2步:在主函数中验证非法访问

接下来编写主函数,尝试通过对象访问各类成员:

int main()
{
  Student1 stud1; // 定义一个Student1类的对象
  
  // 错误!stud1.display(); 编译报错
  // 原因:私有基类的公用成员在派生类中是私有函数,不能由对象直接调用。
  
  stud1.display_1(); // 正确,display_1是Student1的公用函数
  
  // 错误!stud1.age = 18; 编译报错
  // 原因:age属于私有基类的成员或派生类内部私有变量,外界不可引用。
  
  return 0;
}

结论: 私有继承切断了从派生类对象到基类功能的直接路径。

第3步:如何在类内间接调用私有基类成员?

如果必须在类外输出基类信息(例如基类的 display 方法),虽然不能直接在 main 中调用基类方法,但可以通过派生类的成员函数来中转调用。因为基类的公用函数在派生类中变成了私有的,它仍然可以被派生类的其他成员函数调用。

修改派生类的成员函数 display_1:

void display_1() {
  display(); // 在派生类内部调用基类的公用函数(此时它是派生类的私有函数,合法)
  cout<<"age: "<<age<<endl; 
  cout<<"address: "<<addr<<endl;
}

此时的 main 函数非常简洁:

int main()
{
  Student1 stud1;
  stud1.display_1(); // 仅一行即可输出所有数据
  return 0;
}

这种链式调用(外部调派生类公用函数 -> 派生类调基类公用函数 -> 基类访问基类私有成员)是处理私有继承时的标准技巧。

什么是公有继承及其封装意义

将基类的继承方式指定为 public 时,称为公有继承。这是最常用的继承方式,体现了“is-a”的关系。在公有继承下,基类的成员访问属性在派生类中基本保持一致:



  • 基类 public 成员:在派生类中保持 public。派生类对象可以直接访问。
  • 基类 protected 成员:在派生类中保持 protected。派生类可以访问,对象不可访问。
  • 基类 private 成员:**无论何种继承,基类的私有成员永远对派生类不可见。** 它们是隐形的。

第1步:为什么公有继承也不能直接访问基类私有成员?

这是一个重要的软件工程原则。私有成员体现了数据的封装性。如果派生类能直接访问基类的私有成员,那么基类和派生类之间就没有界限了,基类的内部实现细节将被完全暴露给子类。这破坏了面向对象的封闭性,使得系统难以维护和调试。

第2步:正确处理公有继承中的数据访问

在基类 Student 中定义了 num, name, sex 三个私有成员,在派生类 Student1 中定义了 age, addr。

错误的做法(在派生类内部直接引用基类私有变量):

class Student1: public Student 
{
public:
  void display_1() {
    // 以下操作全部报错,num/name/sex是基类的私有成员
    cout<<" num: "<<num<<endl; 
    cout<<" name: "<<name<<endl; 
    cout<<" sex: "<<sex<<endl; 
  }
private:
  int age;
  string addr;
};

正确的做法(通过基类公用成员函数获取数据):

我们可以简化派生类 Student1,只负责打印自己的私有成员:

class Student1: public Student 
{
public:
  void display_1() {
    cout<<" age: "<<age<<endl; 
    cout<<" address: "<<addr<<endl; 
  }
private:
  int age; 
  string addr;
};

然后在 main 中分别调用基类和派生类的公用函数:

int main()
{
  Student1 stud;
  stud.display();      // 调用基类函数,输出3个基类数据
  stud.display_1();    // 调用派生类函数,输出2个派生类数据
  return 0;
}

进一步优化:在派生类的 display_1 中调用基类的 display,使主函数只需一行代码即可完成所有信息的输出。

以上就是C++类继承中公有与私有模式访问规则的详细内容,更多关于C++面向对象基础入门的资料请关注本站其它相关文章!

相关标签:

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。