c++第五章 数据的共享和保护

/*
*一、标识符的作用域和可见性
*     (一)作用域
*           作用域是一个标识符在程序正文中有效的区域
*           c++中标识符(名字)的作用域有函数作用域、局部作用域(块作用域)、类作用域、命名空间作用域
*           1、函数作用域
*              是c++程序中最小的作用域
*              函数原型声明时形参的作用范围解释函数原型作用域
*              函数原型中,标识符没有作用可以省略不写,但是在函数声明时要给出形参标识符
*           2、局部作用域
*             在函数的部分区域有效,具有局部作用域的变量也称为局部变量
*           3、类作用域
*             类可以被看成一组有名成员的集合,类X对成员m具有类作用域,对m的访问方式有以下三种
*             (1)如果x成员函数中没有声明同名的局部作用域标识符,那么在该函数内可以直接访问成员M也就是说m在这样的函数中都起作用
*             (2)通过表达式x.m或者X::m,这是程序中访问对象成员的最基本的方法
*             (3)通过指针,ptr->m
*           4、命名空间作用域
*             (1)命名空间
*             一个大的程序由不同模块构成,不同模块中的类和函数之间有可能发生重名,这样就会引起错误,使用命名空间就会消除这个问题
*             namespace 命名空间{
*                  命名空间内的各种声明(函数声明、类声明、……)           
                                             }
*             一个命名空间确定一个命名空间作用域,在该命名空间内声明的,不属于之前各个作用域的标识符,都属于命名空间作用域
*             命名空间内部可以直接引用当前命名空间中声明的标识符,如果要引用其他命名空间的标识符,则需要
*             命名空间名::表示名符
*              命名空间允许镶套使用
*              namespace OuterNs{//命名空间
*                        namespace InnerNs{//命名空间
*                              class someclass{}//类
                                       }
                                   }
*              (2)using语句
*             但是这一命名方式过于冗杂,于是又提供了using语句
*                using 命名空间::标识符//可以在当前作用域引用这个标识符
*                using namespace 命名空间//在当前作用域,可以引用该命名空间的所有标识符
*                c++标准程序库的所有标识符都在std命名空间内
*                如果去掉using namespace std,则引用需要使用:std::cin;    std::cout;等
*           5、实例(看代码)
*      (二)可见性
            标识符的可见范围就是标识符的可见性,程序运行到某一点,能够引用的标识符,就是该处可见的标识符
*           标识符可见性的一般规则如下:
*           标识符要声明在前,引用在后
*           同一作用域,不能声明同名的标识符
*           在没有互相包含关系的作用域中声明了同名的标识符,互不影响
*           在两个或者两个以上具有包含关系的作用域中声明了同名标识符,则外层在内层不可见
* 二、对象的生存周期
*     对象从诞生到结束的这段时间就是它的而生存周期,在生存周期内,对象将一直保它的状态,变量也将保持它的值不变一直到数据更新为止
*       (一)静态生存期
*            如果对象的生存期与程序的运行期相同,则称它 具有静态生存期
*            在命名空间作用域中声明的对象都具有静态生存期,如果要在函数内部的局部作用域中声明静态生存期的队形,则要使用关键字static
*            static int i;//i是具有静态生存期的变量,也称为静态变量
*            局部作用域中静态变量的特点:
*            不会随着每次函数的调用而产生一个副本,也不会随着函数的返回而失效,也就是说,在下次调用时,,它依旧保持上一回的值
*            即使发生了递归调用,也不会为该变量创建新的副本,每次调用共享
*            在定义静态变量的同时,也可以为他赋初值
*            static int i=5;
*         (二)动态生存期
*             除了命名空间中声明的对象和用关键字static定义的变量外,其余的对象都具有动态生存周期
*             在局部作用域中声明具有动态生存周期的对象,习惯上也称为局部生存期对象,局部生存期对象诞生于声明点,结束与所在块执行完毕时
* 三、类的静态成员
*         模块间的而数据共享是通过函数与函数之间的数据共享来实现的,包括两个途径——参数传递和全局变量
*         静态成员是解决同一个类的不同对象之间数据、函数共享问题的
*          (一)静态数据成员
*                如果某一个属性为整个类所共有的,不属于哪一个具体的对象,则采用static关键字来声明静态成员
*                静态成员在每一个类只有一个副本,由该类的所有对象共同维护和使用,从而事项了一个类不同对象之间的数据共享
*                类属性是描述类的所有对象的共同数据的一个数据项,对于任何对象实例,它的属性值是相同的
*                静态数据成员具有静态生存周期,因为静态数据成员不属于任何一个对象,所以要用类名对他进行访问
*                类名::标识符
*                在类的定义中仅仅对静态成员进行引用性声明,必须在空间作用域的某个地方是由类名限定定义声明,这时可以进行初始化(以这种方式专门为他们分配空间)
*                UML中,数据成员下划线表示静态成员
*          (二)静态函数成员
*                静态成员函数也属于整个类,由同一个类的所有对象所共有,为这些对象所共享
*                静态成员函数可以直接访问该类的静态数据和函数成员,而访问非静态成员,必须通过对象名
*                静态成员函数主要用来访问同一个类中的静态数据成员,维护对象之间共享的数据
*                uml中静态函数成员前面加<<static>>来表示
* 四、类的友元
*          友元关系提供了不同类或对象的成员函数之间、类的成员函数与御坂函数之间进行的共享的机制
*          一个类主动声明了那些类、那些函数是他的朋友从而进行给他们提供对本类的访问特许
*          在一个类中,可以用关键字friend将其他函数或者类的声明为友元
*          (一)友元函数
*                友元函数是在类中用关键字friend修饰的非成员函数,可以是一个普通的函数,也可以是其他类的成员函数
*                可以通过对象名访问类的私有和保护成员
*                uml中函数前面加<<friend>>来表示
*          (二)友元类
*                若a是b的友元类,则A的所有函数都是B的友元函数都可以访问B的私有和保护成员
*                class b{
                            ……      //B类的成员声明
                            friend A ;//声明A是B的友元类
                            ……
                                     }
*            注意:1、有缘不能传递
*                      A是B的友元,B是C的友元,在没有声明A和C的关系时,不存在友元关系
*                      友元关系是单向的
*                      友元关系是不被继承的
* 五、共享数据的保护
*           对于既需要共享又需要防止改变的数据应该声明为常量
*           (一)常对象
*               它的数据成员值在整个生存周期内不能被改变,也就是说,常对象必须进行初始化,并且不能被更新
*               const 类型说明符 对象名
*               常对象的值不能够被改变
*               常量可以被初始化,但是不能进行赋值
*           (二)用const修饰的类成员
*               1、常成员函数
*                使用const关键字修饰的函数为常成员函数
*                 类型说明符   函数名(参数表)const
*                注意:1、const是函数类型的一个组成部分,因此在函数定义部分也要加const
*                      2、如果将一个对象设置为常函数,纳米通过该常函数只能调用它的常成员函数,不能调用其他成员函数
*                      3、无论是否通过常对象调用常成员函数,在常成员函数调用期间,目的对象都被视为常对象,因此常成员函数不能更新目的对象的数据成员
*                      4、const关键字可以用于函数重载
*                           void c();
*                           void c()const;、
*                         是对c函数的有效重载
*                对于不需要改变状态的成员函数都应该使用const关键字
*               2、常数据成员
*                一个类中如果说明了常数据成员,那么任何函数中都不能对该成员赋值,构造函数对该数据成员赋值,只能通过初始化列表、
*                类成员中的静态变量和常量都应该在类定义之外加以定义,但是类的静态常量如果具有整数类型和枚举类型,可以在类中直接定义它为常量值
*               3、常引用
*                如果在声明引用时,用const修饰,被声明的而引用就是常引用,常引用所引用的对象不能更新,如果常引用作为形参,那么它引用的实参将不会发生改变
*                常引用形式
*                     const 类型说明符 &引用名
*                非const的引用只能绑定到普通对象上,不能绑定到常对象,但是常引用可以绑定到常对象上
*                 通过常引用访问绑定对象时,只能把对象当作常对象,
*                 对于基本数据成员,不能为数据赋值、对于类类型的引用,不能修改它的数据成员,也不能调用它不是const类型的函数成员
*               
* 六、多文件结构和编译预处理命令
*           (一)C++的一般组织结构
*                 三部分:类的定义、类的成员的实现、主函数
*                 一个类的定义必须出现在所有使用该类的编译单元中,将类的定义写在头文件中,使用该类的编译单元则包含这个头文件
*                 一个项目通常分为3个文件:类定义文件(*.h)类实现文件(*.cpp)和类的使用文件(*.cpp,主函数文件)
*                 比较复杂的,每一个类都有单独的定义和实现文件,这样,可以对不同的文件单独进行编写、编译,最后的连接
*                  #include<>一般是比较标准的文件
*                  #include""一般自己写的用这种
*                  #include属于预处理文件
*                  决定文件是放在源文件还是头文件:
*                  需要分配空间的定义放在源文件中
*                  内联函数比较特殊,它需要嵌入到每一个调用它的函数中,所以应该放在头文件中
*           (二)外部变量和外部函数
*                  1、外部变量
*                     一个变量除了在定义它的源文件中使用还可以在别的源文件中使用,这样的变量称为外部变量,命名作用域中定义的变量,默认情况下都是外部变量
*                     在其他文件中需要引用这一变量,需要加关键字extern
*                     对外部变量的声明可以是定义性声明(分配内存空间,初始化)也可以是引用性声明(引用定义在别处的变量)
*                  2、外部函数
*                     在类外声明的函数(非成员函数),都具有命名空间作用域,在调用前进行引用性声明就性
*                  (通常情况下,变量和函数的定义都放在源文件中,对外部变量和外部函数的声明则放在头文件中)
*                  3、将函数和变量限制在编译单元内
*                     命名空间作用域中声明的变量和函数,在默认情况下都可以被其他编译单元访问
*                     对于不希望引用的可以
*                      1、使用ststic来进行修饰,ststic修饰的变量和函数将没有办法被别的所引用
*                      static修饰的都具有静态生存期
*                      2、匿名命名空间,
*                       可以把不希望引用函数和变量放在匿名命名空间中
*           (三)标准c++库
*                      是一个非常灵活并且可扩展的可重用软件模块的集合
*                      标准的c++在逻辑上分为以下6种类型
*                      输入输出类
*                      容器类和抽象数据类
*                      存储管理类
*                      算法
*                      错误处理
*                      运行环境支持
*                      using namespase std 不适合放在一个头文件中,防止命名空间对源文件开放
*            (四)编译预处理
*                 编译器对源程序进行编译之前,要由预处理器对程序文本进行预处理
*                 预处理指令不是c++语言的一部分,它是为了扩充c++程序设定的环境
*                 #引导,每一条预处理指令单独占一行,预处理指令可以根据需要出现在程序的任何位置
*                      1、#include指令
*                        文件包含指令,将另一个源文件镶嵌带当前源文件,通常用来插入头文件
*                         可以嵌套使用
*                      2、#define和#undef
*                         #define:1、可以用来定义宏2、定义空符号,仅仅表示符号已经被定义过了
*                         #undef:删除定义的宏,使其之后不起作用
*                      3、条件编译指令
*                          限定条件,在一些条件下,内容才能够被编译
*                        #if  常量表达式//常量表达式非0,编译
*                            程序段
*                         #else if   
*           
*                      #ifdef 标识符//如果标识符被defined定义了且没有被删除,编译
*                            程序段
*                      4、defined操作符
*                        defined是一个预处理操作符,而不是一个指令,不需要以#开头
*                        defined(标识符)
*                        如果标识符被#define定义过切没有被#undef删除则表达式为非0,否则为0;

*/

#include<iostream>
#include<math.h>
using namespace std;
//命名空间,全局变量
namespace Q
{
    int j;//在命名空间Q中的全局变量
}
int i;//全局变量
//静态数据成员
//静态函数成员
class point
{
public:
    point(int x1, int y1) //构造函数
    {
        x = x1;
        y = y1;
        count++;
    }
    static void f(point a);//静态函数成员说明
    point(point& p)//拷贝构造函数
    {
        x = p.x;
        y = p.y;
        count++;
    }
    void showpoint();//函数声明
    void showcount();//函数声明
    
    ~point() { count--; }
private:
    int x;
    int y;
    static int count;//静态成员声明
};
void point::f(point a)
{
    //cout << x;//不能直接访问,要用对象去访问
    cout << a.x;
}
void point::showpoint()
{
    cout << x ;
    cout << y << endl;

}
void point::showcount()
{
    cout << count << endl;
}
int point::count = 0;//静态数据成员定义和初始化,使用类名限定
//使用友元函数计算两点之间的距离
class point1
{
public:
    point1(int a,int b)//构造函数
    {
        x = a;
        y = b;
    }
    point1(point1& a)//复制函数
    {
        x=a.x;
        y = a.y;
    }
    friend float jvli(point1 x,point1 y);
    ~point1() {}//析构函数
private:
    int x;
    int y;
    
};
float jvli(point1 p1, point1 p2)//友元函数的实现
{
    float x = p1.x - p2.x;//友元函数通过对象访问隐私数据
    float y = p1.y - p2.y;
    return sqrt(x * x +y * y);
}
//友元类
class A
{
public:
    A(int x)
    {
        i = x;
    }
     friend class B;
    void show()
    {
        cout << i << endl;
    }
   
private:
    int i;
};
class B
{
public:
  
    friend class A;
    void set(int j);
private:
    A a;
};
void B::set(int j)
{
    a.i = j;
}
//常对象
class C
{
public:
    C(int x,int y)
    {
        i = x;
        j = y;
    }
private:
    int i;
    int j;
};
const C c(1, 2);//c是常对象不能被更新

//常成员函数
class D
{
public:
    D(int x) :a(x) {}
    void print();
    void print()const;
private:
    int a;
};
void D::print()
{
    cout << a<<endl;
}
void D::print()const
{
    cout << 2 * a << endl;
}
//常数据成员
class E
{
public:
    E(int a) :i(a) {}
    void print();
private:
    const int i;
    static const int j;
};
const int E :: j = 2;
void E::print()
{
    cout << i <<j<< endl;
}
//匿名命名空间
namespace
{
    int a;
}
int main()
{
    //常数据成员
    E g(1);
    g.print();
   //常成员函数
    D e(1);
    e.print();
    const D f(1);
    f.print();
    
    //友元函数
    point1 l1(1, 1);
    point1 l2(4, 5);
    cout << jvli(l1, l2) << endl;
    //静态数据成员
    point p(1,2);
    p.showpoint();
    p.showcount();
    point p1(2, 2);
    p1.showpoint();
    p1.showcount();
    //通过p p1访问的是同一个静态成员count,实现两个对象之间的数据共享
    ///命名空间,全局变量
    i = 5;
    Q::j = 6;//给命名空间中的j赋值
    cout << i << endl;
    cout << Q::j << endl;

    {
        using namespace Q;//直接引用命名空间Q,其所在空间的所有标识符都可以用
        i = 6;
        cout << i<< endl;
        cout << j << endl;
    }

}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值