C++学习之数据的共享与保护

  • 标识符的作用域与可见性

作用域是一个标识符在程序正文中有效的区域。

作用域分类:

1、函数原型作用域

2、局部作用域(块作用域)

3、类作用域。

4、文件作用域。

5、命名空间作用域(后面会学习)

  • 函数原型作用域

函数原型中的参数,其作用域始于"(",结束于")"。

例如:

double area(double radius);
  • 局部作用域

函数的形参、在块中声明的标识符。

其作用域自声明处起,限于块中

例如:

void fun(int a) {
   int b = a;
   cin >> b;
   if (b > 0) {
     int c;
     ......
   }
}
  • 类作用域

类的成员具有类作用域,其范围包括类体非内联成员函数的函数体。

如果在类作用域以外访问类的成员,要通过类名(访问静态成员),或者该类的对象名、对象引用、对象指针(访问非静态成员)。

  • 文件作用域

不在前述各个作用域中出现的声明,就具有文件作用域,这样声明的标识符其作用域开始于声明点,结束于文件尾。

  • 可见性

可见性是从对标识符的引用的角度来谈的概念。

可见性表示从内层作用域向外层作用域“看”时能看见什么。

如果标识在某处可见,就可以在该处引用此标识符。

如果某个标识符在外层中声明,且在内层中没有同一标识符的声明,则该标识符在内层可见。

对于两个嵌套的作用域,如果在内层作用域内声明了与外层作用域中同名的标识符,则外层作用域的标识符在内层不可见。

例如:

//5_1.cpp
#include 
using namespace std;
 
int i;	//全局变量,文件作用域
int main() { 
     i = 5; //为全局变量i赋值
     {
         int i; //局部变量,局部作用域
         i = 7;
         cout << "i = " << i << endl;//输出7
      }
      cout << “i = ” << i << endl;//输出5
      return 0;
}
  • 对象的生存期

静态生存期:

1、这种生存期与程序的运行期相同。

2、在文件作用域中声明的对象具有这种生存期。

3、在函数内部声明静态生存期对象,要冠以关键字static 

动态生存期:

块作用域中声明的,没有用static修饰的对象是动态生存期的对象(习惯称局部生存期对象)。

开始于程序执行到声明点时,结束于命名该标识符的作用域结束处。

例如:

#include<iostream>
using namespace std;
int i = 1;         // i 为全局变量,具有静态生存期。
void other() {
static int a = 2;
static int b;
// a,b为静态局部变量,具有全局寿命,局部可见。
//只第一次进入函数时被初始化。
int c = 10;     // C为局部变量,具有动态生存期,

//每次进入函数时都初始化。
a += 2; i += 32; c += 5;
cout<<"---OTHER---\n";
cout<<" i: "<<i<<" a: "<<a<<" b: "<<b<<" c: "<<c<<endl;
b = a;
}

int main() {
static int a;    //静态局部变量,有全局寿命,局部可见。
int b = -10;     // b, c为局部变量,具有动态生存期。
int c = 0;
cout << "---MAIN---\n";
cout<<" i: "<<i<<" a: "<<a<<" b: "<<b<<" c: "<<c<<endl;
c += 8; other();
cout<<"---MAIN---\n";
cout<<" i: "<<i<<" a: "<<a<<" b: "<<b<<" c: "<<c<<endl;
i += 10; other();
return 0;
}

上面程序的运行结果是:

---MAIN---
i: 1 a: 0 b: -10 c: 0
---OTHER---
i: 33 a: 4 b: 0 c: 15
---MAIN---
i: 33 a: 0 b: -10 c: 8
---OTHER---
i: 75 a: 6 b: 4 c: 15
  • 类的静态成员

静态数据成员:

1、用关键字static声明。

2、为该类的所有对象共享,静态数据成员具有静态生存期。

3、必须在类外定义和初始化,用(::)来指明所属的类。

例如:具有静态数据成员的Point类:

#include <iostream>
using namespace std;

class Point {     //Point类定义
public:       //外部接口
       Point(int x = 0, int y = 0) : x(x), y(y) { //构造函数
           //在构造函数中对count累加,所有对象共同维护同一个count
           count++;
       }
       Point(Point &p) {    //复制构造函数
           x = p.x;
           y = p.y;
           count++;
       }

       ~Point() {  count--; }
       int getX() { return x; }
       int getY() { return y; }
       void showCount() {           //输出静态数据成员
           cout << "  Object count = " << count << endl;
       }

private:      //私有数据成员
       int x, y;
       static int count;       //静态数据成员声明,用于记录点的个数
};

int Point::count = 0;//静态数据成员定义和初始化,使用类名限定
int main() {       //主函数
       Point a(4, 5);     //定义对象a,其构造函数回使count增1
       cout << "Point A: " << a.getX() << ", " << a.getY();
       a.showCount(); //输出对象个数
       Point b(a); //定义对象b,其构造函数回使count增1
       cout << "Point B: " << b.getX() << ", " << b.getY();
       b.showCount();       //输出对象个数
       return 0;
}

程序的运行结果是:

Point A: 4, 5  Object count=1

Point B: 4, 5  Object count=2

  • 静态函数成员

类外代码可以使用类名作用域操作符来调用静态成员函数。

静态成员函数主要用于处理该类的静态数据成员,可以直接调用静态成员函数

如果访问非静态成员,要通过对象来访问。

例如:具有静态数据、函数成员的Point类:

#include <iostream>
using namespace std;

class Point {    
public:      
       Point(int x = 0, int y = 0) : x(x), y(y) {  count++; }//构造函数                  
       Point(Point &p) {    //复制构造函数
           x = p.x;
           y = p.y;
           count++;
       }

       ~Point() {  count--; }
       int getX() { return x; }
       int getY() { return y; }
       static void showCount() {   
       cout << "  Object count = " << count << endl;
       }

private:     
       int x, y;
       static int count;       //静态数据成员声明,用于记录点的个数
};

int Point::count = 0;//静态数据成员定义和初始化,使用类名限定

int main() {      
       Point a(4, 5);     //定义对象a,其构造函数回使count增1
       cout << "Point A: " << a.getX() << ", " << a.getY();
       Point::showCount();       //输出对象个数
       Point b(a); //定义对象b,其构造函数回使count增1
       cout << "Point B: " << b.getX() << ", " << b.getY();
       Point::showCount();       //输出对象个数
       return 0;
}

  • 类的友元

友元是C++提供的一种破坏数据封装和数据隐藏的机制。

通过将一个模块声明为另一个模块的友元,一个模块能够引用到另一个模块中本是被隐藏的信息。

可以使用友元函数友元类

为了确保数据的完整性,及数据封装与隐藏的原则,建议尽量不使用或少使用友元。

友元函数:

友元函数是在类声明中由关键字friend修饰说明的非成员函数,在它的函数体中能够通过对象名访问 private 和protected成员

作用:增加灵活性,使程序员可以在封装和快速性方面做合理选择。

访问对象中的成员必须通过对象名。

例如:利用友元函数计算两点之间的距离

#include <iostream>
#include <cmath>
using namespace std;

class Point { //Point类声明
public: //外部接口
    Point(int x=0, int y=0) : x(x), y(y) { }
    int getX() { return x; }
    int getY() { return y; }
    friend float dist(Point &a, Point &b);
private: //私有数据成员
    int x, y;
};

float dist( Point& a, Point& b) {
    double x = a.x - b.x;
    double y = a.y - b.y;
return static_cast<float>(sqrt(x * x + y * y));
}

int main() {
    Point p1(1, 1), p2(4, 5);
    cout <<"The distance is: ";
    cout << dist(p1, p2) << endl;
    return 0;
}

友元类:

若一个类为另一个类的友元,则此类的所有成员都能访问对方类的私有成员。

声明语法:将友元类名在另一个类中使用friend修饰说明。

例如:

class A {
friend class B;
public:
void display() {
cout << x << endl;
}
private:
int x;
};

class B {
public:
void set(int i);
void display();
private:
A a;
};

void B::set(int i) {
a.x=i;
}
void B::display() {
a.display();
};

类的友元关系是单向的:

如果声明B类是A类的友元,B类的成员函数就可以访问A类的私有和保护数据,但A类的成员函数却不能访问B类的私有、保护数据。

 

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值