c++数据的共享保护

作用域

  • 函数原型作用域
    函数原型中的参数,其作用域始于"(",结束于")"。
  • 局部作用域
    函数的形参,在块中声明的标识符,其作用域自声明处起,限于块中
  • 类作用域
    1. 作用于特定的成员名。
    2. 类X的成员m具有类作用域,对m的访问方式如下:
      1. 如果在X的成员函数中没有声明同名的局部作用域标识符,那么在该函数内可以访问成员m。
      2. 通过表达式x.m或者X::m访问。
      3. 通过表达式ptr->m
  • 文件作用域
    不在前述各个作用域中出现的声明,具有文件作用域,这样声明的标识符的作用域开始于声明点,结束于文件尾。

#include
using namespace std;
int i; //文件作用域
int main() {
i = 5;
{
int i; //块作用域
i = 7;
cout << "i = " << i << endl; //输出7
}
cout << "i = " << i; //输出5
return 0;
}

可见性

•可见性是从对标识符的引用的角度来谈的概念
• 可见性表从内层作用域向外层作用域“看”时能看见什么
• 如果标识在某处可见,则就可以在该处使用此标识符。
• 标识符应声明在先,引用在后。
• 如果某个标识符在外层中声明,且在内层中没有同一标识符的声明,则该标识符在内层可见。
• 对于两个嵌套的作用域,如果在内层作用域内声明了与外层作用域中同名的标识符,则外层作用域的标识符在内层不可见。

对象的生命期

对象从产生到结束的这段时间就是它的生存期。 在对象生存期内,对象将保持它的值,直到被更新为止。

  • 静态生命期
    1)这种生存期与程序的运行期相同。
    2)在文件作用域中声明的对象具有这种生存期。
    3) 在函数内部声明静态生存期对象,要加static 。
  • 动态生命期
    1) 块作用域中声明的,没有用static修饰的对象是动态生存期的对象(习惯称局部生存期对象)。
    2)开始于程序执行到声明点时,结束于命名该标识符的作用域结束处。

main函数中的a和other函数中的a不属于同一个,他们会开辟两块独立的静态空间
c++数据的共享保护

静态成员

  • 静态数据成员

    1. 用关键字static声明
    2. 该类的所有对象维护该成员的同一个拷贝
    3. 必须在类外定义和初始化,用(::)来指明所属的类。

      c++数据的共享保护

  • 静态成员函数

    1. 类外代码可以使用类名和作用域操作符来调用静态成员函数。
    2. 静态成员函数只能引用属于该类的静态数据成员或静态成员函数。

      c++数据的共享保护

友元

  • 友元是C++提供的一种破坏数据封装和数据隐藏的机制。
  • 通过将一个模块声明为另一个模块的友元,一个模块能够引用到另一个模块中本是被隐藏的信息。
  • 可以使用友元函数和友元类。
  • 为了确保数据的完整性,及数据封装与隐藏的原则,建议尽量少使用友元。
友元函数
  • 友元函数是在类声明中由关键字friend修饰说明的非成员函数,在它的函数体中能够通过对象名访问 private和protected成员
  • 作用:增加灵活性,使程序员可以在封装和快速性方面做合理选择。
  • 访问对象中的成员必须通过对象名。

c++数据的共享保护

友元类
  1. 类为另一个类的友元,则此类的所有成员都能访问对方类的私有成员。
  2. 声明语法:将友元类名在另一个类中使用friend修饰说明
  3. 如果声明B类是A类的友元, B类的成员函数就可以访问A类的私有和保护数据,但A类的成员函数却不能访问B类的私有、保护数据。

c++数据的共享保护

共享数据的保护

常类型

常类型的对象必须进行初始化,而且不能被更新。

  • 常对象:必须进行初始化,不能被更新。
    类名 const 对象名

c++数据的共享保护
通过常对象只能调用它的常成员函数。
c++数据的共享保护

  • 常引用:被引用的对象不能被更新。
    const 类型说明符 &引用名

c++数据的共享保护
不可以更改r的指向
c++数据的共享保护

  • 常数组:数组元素不能被更新
    类型说明符 const 数组名[大小]…
  • 常指针:指向常量的指针
用const 修饰的对象成员
  • 常成员函数
    1. 使用const关键字说明的函数。
    2. 常成员函数不更新对象的数据成员。
    3. 常成员函数说明格式:
      类型说明符 函数名(参数表) const;
      这里, const是函数类型的一个组成部分,因此在实现部分也要带const关键字。
    4. const关键字可以被用于参与对重载函数的区分
    5. 通过常对象只能调用它的常成员函数。
    6. 常成员函数的声明原则
      • 适当地将成员函数声明为常成员函数,能够提高代码质量。
      • 凡是不会改变对象状态的函数,都应当声明为常成员函数。
      • 什么是改变对象状态?
      1. 改变对象状态,不简单地等同于改变成员数据的值。
      2. 只要一个成员函数执行与否,不会影响以后接口函数的调用结果,都认为它不会改变对象状态。
        • mutable关键字使得被修饰的成员对象无视“常对象的成员对象被视为常对象”这一语言原则

c++数据的共享保护

  • 常数据成员
    使用const说明的数据成员。

c++数据的共享保护c++数据的共享保护

多文件结构

  • 一个源程序可以划分为多个源文件:
    1. 类声明文件(.h文件)
    2. 类实现文件(.cpp文件)
    3. 类的使用文件(main()所在的.cpp文件)

代码的编译连接与执行

  • 编译:源文件–>目标文件
    1. 源文件的函数代码–>目标文件的代码段
    2. 源文件的静态对象–>目标文件的数据段
      分为初始化的数据段和未初始化的数据段
    3. 符号表:将静态对象与函数的名字与地址关联
    4. 重定位记录表:将代码中需用到的地址与符号表关联
  • 连接
    1. 将各段合并
    2. 将符号表合并
    3. 根据重定位记录表,确定代码中用到的全局地址 根据重定位记录表,确定代码中用到的全局地址
  • 代码的执行
    1. 操作系统首先将文件从磁盘读入,初始化各段——一些静态数据就在此时被初始化
    2. 从引导代码开始执行,引导代码启动main,main返回后,引导代码会通知操作系统程序结束
  • 为什么只有静态对象需要在目标文件中保存信息?
    连接器负责为静态对象分配唯一地址,而其它对象都是相对寻址
  • 为什么类的信息不存在于目标文件中?
    类的“解构”