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++派生访问说明符、派生类向基类转换的可访问性、改变个别成员的可访问性、默认的继承保护级别的内容。

相关实践学习
消息队列+Serverless+Tablestore:实现高弹性的电商订单系统
基于消息队列以及函数计算,快速部署一个高弹性的商品订单系统,能够应对抢购场景下的高并发情况。
云安全基础课 - 访问控制概述
课程大纲 课程目标和内容介绍视频时长 访问控制概述视频时长 身份标识和认证技术视频时长 授权机制视频时长 访问控制的常见攻击视频时长
目录
相关文章
|
2月前
|
移动开发 监控 Android开发
Android & iOS 使用 ARMS 用户体验监控(RUM)的最佳实践
本文主要介绍了 ARMS 用户体验监控的基本功能特性,并介绍了在几种常见场景下的最佳实践。
333 12
|
27天前
|
编译器 C++ 开发者
【C++】继承
C++中的继承是面向对象编程的核心特性之一,允许派生类继承基类的属性和方法,实现代码复用和类的层次结构。继承有三种类型:公有、私有和受保护继承,每种类型决定了派生类如何访问基类成员。此外,继承还涉及构造函数、析构函数、拷贝构造函数和赋值运算符的调用规则,以及解决多继承带来的二义性和数据冗余问题的虚拟继承。在设计类时,应谨慎选择继承和组合,以降低耦合度并提高代码的可维护性。
32 1
【C++】继承
|
2月前
|
安全 程序员 编译器
【C++篇】继承之韵:解构编程奥义,领略面向对象的至高法则
【C++篇】继承之韵:解构编程奥义,领略面向对象的至高法则
90 11
|
2月前
|
C++
C++番外篇——对于继承中子类与父类对象同时定义其析构顺序的探究
C++番外篇——对于继承中子类与父类对象同时定义其析构顺序的探究
63 1
|
2月前
|
C++
C++番外篇——虚拟继承解决数据冗余和二义性的原理
C++番外篇——虚拟继承解决数据冗余和二义性的原理
45 1
|
2月前
|
安全 编译器 程序员
C++的忠实粉丝-继承的热情(1)
C++的忠实粉丝-继承的热情(1)
21 0
|
3月前
|
Java Android开发 C++
🚀Android NDK开发实战!Java与C++混合编程,打造极致性能体验!📊
在Android应用开发中,追求卓越性能是不变的主题。本文介绍如何利用Android NDK(Native Development Kit)结合Java与C++进行混合编程,提升应用性能。从环境搭建到JNI接口设计,再到实战示例,全面展示NDK的优势与应用技巧,助你打造高性能应用。通过具体案例,如计算斐波那契数列,详细讲解Java与C++的协作流程,帮助开发者掌握NDK开发精髓,实现高效计算与硬件交互。
166 1
|
2月前
|
编译器 C++
C++入门11——详解C++继承(菱形继承与虚拟继承)-2
C++入门11——详解C++继承(菱形继承与虚拟继承)-2
39 0
|
2月前
|
程序员 C++
C++入门11——详解C++继承(菱形继承与虚拟继承)-1
C++入门11——详解C++继承(菱形继承与虚拟继承)-1
41 0
|
3月前
|
C++
C++(二十)继承
本文介绍了C++中的继承特性,包括公有、保护和私有继承,并解释了虚继承的作用。通过示例展示了派生类如何从基类继承属性和方法,并保持自身的独特性。此外,还详细说明了派生类构造函数的语法格式及构造顺序,提供了具体的代码示例帮助理解。