Android C++系列:C++最佳实践3继承与访问控制

简介: 整个结构还是比较简单的,从类内部到本包到子类到外部包权限越来越小,比较好理解也比较好记忆。但是在C++中访问控制要复杂很多,因为不仅有属性和方法的访问控制,还有继承时的派生列表访问说明符。今天我们着重了解访问控制。

image.png


1. 背景


Java中有四种访问控制:public、protected、default、private,它们的使用范围可以用下面一张表概括:


类内部 本包 子类 外部包
public
protected
default
private


整个结构还是比较简单的,从类内部到本包到子类到外部包权限越来越小,比较好理解也比较好记忆。但是在C++中访问控制要复杂很多,因为不仅有属性和方法的访问控制,还有继承时的派生列表访问说明符。今天我们着重了解访问控制。


2. 受保护的成员protected


在Java中我们一般默认子类可以访问父类的protected,但是C++中要更复杂些。它有三个特征:


  1. 受保护的成员对于类的用户来说是不可访问的;
  2. 受保护的成员对于派生类的成员和友元来说是可访问的;
  3. 派生类的成员或友元只能通过派生类对象来访问积累的受保护成员,派生类对于一个基类对象中的受保护成员没有任何访问特权。


怎么理解第三点呢?举个例子:


class Base{
protected:
  int num;
}
class Sub:public Base{
  friend void set(Sub&);
  friend void set(Base&);
  int i;
}
void set(Sub& sub){
  sub.i = sub.num = 0;//正确,可以访问基类和派生类的成员
}
void set(Base &base){
  base.num = 0;//错误,不能访问基类的成员
}


为什么要这样设计呢?如果派生类的友元可以直接访问基类的受保护成员,那么我们对任何类,只要设计它的子类,在子类的友元函数中就可以访问基类受保护的成员了,破坏了设计访问控制的目的,这一点比Java要严谨一些,任何访问控制都会被反射虐的体无完肤。


所以这里的结论是:派生类的成员和友元只能访问派生类对象中的基类部分的受保护成员,对于普通的基类对象中的成员不具有特殊的访问权限。


3. 派生访问说明符


派生访问说明符的目的是控制抱愧派生类的派生类在内的派生类用户对于基类成员的访问权限:


  1. 如果继承是公有的,则成员将遵循其原有的访问说明符;
  2. 如果继承是私有的,派生类中基类的公有成员也会变成私有。


4. 派生类向基类转换的可访问性


派生类向基类的转换是否可访问由使用该转换的代码决定,同时派生类的派生访问说明符也会有影响:


  1. 只有Son公有的继承Base时,用户代码才能使用派生类向接力的转换;如果是私有或者受保护,则用户代码不能使用该转换;
  2. 不论子类以什么方式继承父类,子类的成员函数和友元都能使用派生类向基类的转换;派生类向其直接基类的类型转换对于派生类的成员和友元是永远可访问的;
  3. 如果是工友或者受保护的继承,子类的派生类的成员和友元可以使用子类向基类的转换;反之不行。


5. 改变个别成员的可访问性


我们经常在代码中看到using Base::size这样的语句,很蒙圈不知道是干什么。这里是为了改变派生类继承的某个名字的访问级别。比如我们大部分内容想要私有继承,那么派生类列表访问类型使用私有就行。但是如果私有继承时某个或者某几个字段想要公开就可以使用using语句。举个例子:


class Base{
public:
  int size() const{
    return n;
  }
protected:
  int n;
};
class Sub:private Base{
public:
  //保持size函数的可访问性
  using Base::size;
protected:
  using Base::n;
} 


6. 默认的继承保护级别


有时候我们很困惑strcut和class关键字的区别,其实它们唯一的区别就是具有不同的默认访问说明符和默认派生运算符。但是我们规范书写代码的话都尽量不适用默认访问权限,所以很多时候struct和class区别不大。


7. 总结


文本介绍了Java和C++访问控制权限的区别,以及C++派生访问说明符、派生类向基类转换的可访问性、改变个别成员的可访问性、默认的继承保护级别的内容。

目录
相关文章
|
11月前
|
移动开发 监控 Android开发
Android & iOS 使用 ARMS 用户体验监控(RUM)的最佳实践
本文主要介绍了 ARMS 用户体验监控的基本功能特性,并介绍了在几种常见场景下的最佳实践。
833 99
|
3月前
|
存储 安全 Java
c++--继承
c++作为面向对象的语言三大特点其中之一就是继承,那么继承到底有何奥妙呢?继承(inheritance)机制是面向对象程序设计使代码可以复用的最重要的手段,它允许程序员在保持原有类特性的基础上进行扩展,增加功能,这样产生新的类,称派生类。继承呈现了面向对象程序设计的层次结构,体现了由简单到复杂的认知过程。以前我们接触的复用都是函数复用,继承是类设计层次的复用,继承就是类方法的复用。
81 0
|
6月前
|
安全 C++
【c++】继承(继承的定义格式、赋值兼容转换、多继承、派生类默认成员函数规则、继承与友元、继承与静态成员)
本文深入探讨了C++中的继承机制,作为面向对象编程(OOP)的核心特性之一。继承通过允许派生类扩展基类的属性和方法,极大促进了代码复用,增强了代码的可维护性和可扩展性。文章详细介绍了继承的基本概念、定义格式、继承方式(public、protected、private)、赋值兼容转换、作用域问题、默认成员函数规则、继承与友元、静态成员、多继承及菱形继承问题,并对比了继承与组合的优缺点。最后总结指出,虽然继承提高了代码灵活性和复用率,但也带来了耦合度高的问题,建议在“has-a”和“is-a”关系同时存在时优先使用组合。
324 6
|
8月前
|
C++ 开发者
C++学习之继承
通过继承,C++可以实现代码重用、扩展类的功能并支持多态性。理解继承的类型、重写与重载、多重继承及其相关问题,对于掌握C++面向对象编程至关重要。希望本文能为您的C++学习和开发提供实用的指导。
130 16
|
8月前
|
编译器 数据安全/隐私保护 C++
【C++面向对象——继承与派生】派生类的应用(头歌实践教学平台习题)【合集】
本实验旨在学习类的继承关系、不同继承方式下的访问控制及利用虚基类解决二义性问题。主要内容包括: 1. **类的继承关系基础概念**:介绍继承的定义及声明派生类的语法。 2. **不同继承方式下对基类成员的访问控制**:详细说明`public`、`private`和`protected`继承方式对基类成员的访问权限影响。 3. **利用虚基类解决二义性问题**:解释多继承中可能出现的二义性及其解决方案——虚基类。 实验任务要求从`people`类派生出`student`、`teacher`、`graduate`和`TA`类,添加特定属性并测试这些类的功能。最终通过创建教师和助教实例,验证代码
174 5
|
10月前
|
编译器 C++ 开发者
【C++】继承
C++中的继承是面向对象编程的核心特性之一,允许派生类继承基类的属性和方法,实现代码复用和类的层次结构。继承有三种类型:公有、私有和受保护继承,每种类型决定了派生类如何访问基类成员。此外,继承还涉及构造函数、析构函数、拷贝构造函数和赋值运算符的调用规则,以及解决多继承带来的二义性和数据冗余问题的虚拟继承。在设计类时,应谨慎选择继承和组合,以降低耦合度并提高代码的可维护性。
139 1
【C++】继承
|
11月前
|
安全 程序员 编译器
【C++篇】继承之韵:解构编程奥义,领略面向对象的至高法则
【C++篇】继承之韵:解构编程奥义,领略面向对象的至高法则
173 11
|
11月前
|
C++
C++番外篇——对于继承中子类与父类对象同时定义其析构顺序的探究
C++番外篇——对于继承中子类与父类对象同时定义其析构顺序的探究
119 1
|
11月前
|
C++
C++番外篇——虚拟继承解决数据冗余和二义性的原理
C++番外篇——虚拟继承解决数据冗余和二义性的原理
119 1
|
12月前
|
Java Android开发 C++
🚀Android NDK开发实战!Java与C++混合编程,打造极致性能体验!📊
在Android应用开发中,追求卓越性能是不变的主题。本文介绍如何利用Android NDK(Native Development Kit)结合Java与C++进行混合编程,提升应用性能。从环境搭建到JNI接口设计,再到实战示例,全面展示NDK的优势与应用技巧,助你打造高性能应用。通过具体案例,如计算斐波那契数列,详细讲解Java与C++的协作流程,帮助开发者掌握NDK开发精髓,实现高效计算与硬件交互。
382 1