数据的共享与保护

🗨️字数统计=1.3k字 ⏳阅读时长≈4分钟

一、标识符的作用域与可见性


二、对象的生存期

1. 静态生存期

  • 这种生存期与程序的运行期相同。
  • 在文件作用域中声明的对象具有这种生存期。
  • 在函数内部声明静态生存期对象,要冠以关键字 static

2. 动态生存期

  • 块作用域中声明的,没有用static修饰的对象是动态生存期的对象(习惯称局部生存期对象)。
  • 开始于程序执行到声明点时,结束于命名该标识符的作用域结束处。

三、变量的生存期与可见性综合示例





思考:在函数内部定义的普通局部变量和静态局部变量在功能上有何不同?计算机底层对这两类变量做了
怎样的不同处理?

  • 局部作用域中的静态变量: 不会随着每次函数的调用而产生一个副本,也不会随着函数的返回而失效,定义时未指定初值的会被以0初始化
  • 局部作用域中的全局变量:诞生于声明点,结束于声明所在块执行完毕之时,并且不指定初值意味着初值不确定

四、类的静态成员 static

静态成员函数/变量本质上是全局函数/变量,哪怕一个对象都不存在,类的静态成员都还是存在的。


那为什么还要设置静态成员而不直接设置成全局函数/变量呢?

  • 是为了将和某些类紧密相关的全局变量和函数写到类里面,使其看上去像一个整体,便于维护和理解。


注:私有的静态成员在类外依然不能访问

1. 静态成员变量



1
2
3
4
5
class A{
int n;
static int s;
}
int A :: s = 2; //类外初始化
  • 所有对象共享,维护同一个副本,即对象 n1 修改其值,对象 n2 中的值也会改变。
  • sizeof(A) = 4;sizeof不会计算静态成员变量
  • 静态成员变量必须在类外进行一次说明或初始化,否则编译能通过但链接不能通过

2. 静态成员函数


普通成员函数必须具体作用于某个对象(即通过 对象名. 访问),
而静态成员函数并不具体作用于某个对象,不需要通过对象就能访问。


静态成员函数的访问方式:

  • 类名::成员名(无须对象,直接通过类名访问)
1
Point::showCount();
  • 对象名.成员名
1
2
A a; 
a.s( );


但并不意味着只作用于a上面

  • 指针->成员名
1
2
A *p; 
p->s( );


但并不意味着只作用于a上面

  • 引用.成员名
1
2
A &q = a; 
q.s( );


但并不意味着只作用于a上面

注:静态成员函数要访问非静态成员变量必须通过对象名.

1
2
3
4
5
6
7
8
9
10
class A
{
int x;
public:
static void func(A a)
{
cout << x; //ERROR!!!
cout << a.x;
}
}

五、类的友元 friend


1. 友元函数


2. 友元类




特别注意:友元关系不能继承;不能传递;单向 !

六、共享数据的保护 (const)


Java 中没有 const 关键字,与之替代的是 final

1. 常对象

用 const 修饰的对象

  • 常量对象的值不可被修改
  • 常量对象不能执行非常量成员函数,因为非常量成员函数有可能对成员变量进行修改;
  • 常量对象可以执行常量成员函数


例:

1
2
3
4
5
6
7
8
9
10
11
class A{
public:
A(int i, int j){
x = i;
y = j;
}
private:
int x, y;
};

A const a(3,4); //常对象a,不能被更新

2. 常成员

用 const 修饰的对象成员

常成员函数


例:



常成员函数执行期间不应该修改其所作用的对象,即

  • 在常量成员函数中不能修改成员变量的值(静态成员变量除外)
  • 也不能调用同类的非常量成员函数(静态成员函数除外)

例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class A{
public:
int value;
void setValue() const;
void func();
}
void A :: setValue(){
value = 0; //wrong 常量成员函数中不能修改成员变量的值
func(); //wrong 常量成员函数中不能调用同类的非常量成员函数
}
const A a;
a.value = 100; //wrong 常量对象的值不可被修改
a.func(); //wrong 常量对象不能执行非常量成员函数
a.setValue(); //right 常量对象可以执行常量成员函数

常数据成员

使用 const 说明的数据成员

  • 常数据成员 const 只能通过构造函数的初始化列表来获得初值
  • 静态常数据成员 static const 在类外进行说明和初始化


例:

3. 常引用

当需要对象作为参数时,生成该参数需要调用复制构造函数,效率比较低,用指针做参数,代码会比较不好看,所以用对象的引用做参数
void func(A &a)


使用对象引用作参数有一定的风险性,若函数中修改了形参a,则实参也跟着变,有时候这可能不是开发者想要的。若不想要对象发生改变,则使用const限定:
void func(const A &a)



例:

分享到