广告位联系
返回顶部
分享到

C++的数据共享与保护的介绍

C语言 来源:互联网 作者:秩名 发布时间:2022-03-13 19:49:56 人浏览
摘要

1.作用域 作用域是一个标识符在程序正文中有效的区域 作用域关系从大到小为: 命名空间作用域 类作用域 局部作用域 标识符的有效范围就是标识符的可见性,可见性的一般规则为:

1.作用域

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

作用域关系从大到小为:

命名空间作用域 > 类作用域 > 局部作用域

标识符的有效范围就是标识符的可见性,可见性的一般规则为:

  • 标识符声明在前,使用在后
  • 在同一作用域中,不能声明同名的标识符
  • 在没有包含关系的不同的作用域中声明的同名标识符,互不影响
  • 如果在多个作用域中定义了同名标识符,则外层标识符在内层不可见

2.对象生存期

如果对象生存期与程序的运行期相同,则它具有静态生存期

局部生存期对象诞生于声明点,结束于声明所在块执行完毕之时

  • 命名空间作用域中声明的对象都具有静态生存期
  • 定义时未指定初值的基本类型静态生存期变量,会被赋予0值初始化
  • 如果要在函数内部的局部作用域中声明具有静态生存期的对象,则要使用关键字static

1

2

3

4

5

6

void f()

{

    static int m=0; //m仅在f中能访问

    m++;

    cout<<m<<endl;

}

静态数据成员

如果某个属性为整个类所共有,可以采用static关键字来声明为静态成员。

  • 静态成员在每个类中只有一个副本,由该类的所有对象共同维护和使用
  • 在类中不能对static静态数据成员进行初始化,要初始化必须在类外进行定义

1

2

3

4

5

6

7

8

9

10

11

class A{

public:

    static int m;

};

int A::m=20;            //在类外进行初始化

int main(){

    A a,b;

    a.m=10;             //可以赋值

    cout<<a.m<<endl;

    cout<<b.m<<endl;    //两者的值相同

}

静态成员函数

  • 静态成员函数可以通过类名或对象名来进行调用,非静态成员函数只能通过对象名来调用
  • 静态成员函数可以直接访问该类的静态数据和函数成员,而访问非静态成员,必须通过对象名

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

class A{

public:

    static void f(A a);

    static void g(){

        cout<<"hello"<<endl;

    }

    void fun(){

        cout<<"world"<<endl;

    }

private:

    int x;

    static int y;

};

int A::y=10;

void A::f(A a){

    cout<<a.x<<endl;    //必须通过对象名访问

    cout<<y<<endl;      //直接访问该类的静态数据成员

    g();                //直接访问该类的静态成员函数

}

int main(){

    A a;

    A::f(a);            //直接通过类名调用

    return 0;

}

3.类的友元

友元关系是一种数据共享机制,通过友元关系,一个普通函数或者类中的成员函数可以访问封装于另外一个类中的数据

为了确保数据的完整性和封闭性,建议尽量少地使用友元

友元函数

友元函数是类中用关键字friend修饰的非成员函数,在它的函数体中可以通过对象名访问类的private和protected成员

1

2

3

4

5

6

7

8

9

10

class A{

public:

    friend int main();

private:

    int x;

};

int main(){

    A a;

    a.x=5;  //访问 private对象

}

友元类

若B类为A类的友元类,则B类的所有成员函数都是A类的友元函数,都可以访问A类的private和protected成员

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

class A{

public:

    friend class B;

private:

    int x,y;

    void f(){

        cout<<x<<endl;

    }

};

class B{

public:

    void print(){

        a.x=5;

        a.y=10;

        cout<<a.y<<endl;//可以访问A类对象的私有成员

        a.f();          //可以访问A类对象的私有函数

    }

private:

    A a;

};

注意(!!!)

1.友元关系是单向的。

B类是A类的友元,B能访问A的私有数据,但A不能访问B的私有数据

2.友元关系不能传递。B是A的友元,C是B的友元,C和A之间如果没有声明就不存在友元关系

3.友元关系不能被继承。 

4.共享数据的保护

常对象

数据成员值在对象的整个生存期间不能被修改的对象叫做常对象,一般用const进行修饰

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

声明常对象的语法形式为:

const 类型说明符 对象名;

1

2

3

4

5

6

7

8

9

class A{

public:

    A(int i,int j):x(i),y(j){···}

private:

    int x,y;

};

int main(){

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

}

常成员函数

使用const关键字修饰的函数为常成员函数

语法:

类型说明符 函数名(参数表)const;

如果将一个对象说明为常对象,通过该常对象只能调用它的常成员函数,不能调用其他函数(常对象唯一的对外接口方式)

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

class A{

public:

    A(int i,int j):x(i),y(j){···}

    void print(){

        cout<<x<<" "<<y<<endl;

    }

    void print() const{

        //常成员函数

        cout<<x<<" const "<<y<<endl;

    }

private:

    int x,y;

};

int main(){

    A a(1,2);

    a.print();  //调用 void print()

    const A b(3,4);

    b.print();  //调用 void print() const

}

使用const说明的数据成员为常数据成员

类中说明了常数据成员,任何函数不能对它赋值,构造函数对它进行初始化只能通过初始化列表

1

2

3

4

5

6

7

8

9

class A{

public:

    //常数据成员只能通过构造函数的初始化列表来获得初值

    A(int i):a(i){···}

private:

    const int a;       //常数据成员

    static const int b;//静态常数据成员

};

const int A::b=10;  //静态常数据成员在类外初始化

常引用

如果在声明引用时用const修饰,被声明的引用就是常引用,常引用所引用的对象不能被更新

常引用的声明形式:

const 类型说明符 & 引用名;

一个常引用,无论是绑定到一个普通对象,还是一个常对象,通过该引用访问该对象时,都只能把该对象当做常对象

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

class Point{

public:

    Point(int x,int y):x(x),y(y){}

    friend float dist(const Point &p1,const Point &p2);

private:

    int x,y;

};

float dist(const Point &p1,const Point &p2){   //常引用作形参

    double x=p1.x-p2.x;

    double y=p1.y-p2.y;

    return sqrt(x*x+y*y);

}

int main(){

    const Point m1(1,1),m2(4,5);

    cout<<dist(m1,m2)<<endl;    //两点间距离

}

Tips

  • include书写方式
    • include <文件名>,按照标准方式搜索嵌入文件,文件位于编译环境include子目录下。示例:include <iostream>
    • include “文件名”,在当前目录下搜索嵌入文件,如果搜不到则转为标准搜索。示例:include "point.h"
  • 外部变量
    • 如果一个变量可以在本文件和其他文件中使用,称为外部变量,用 extern 关键字说明

extern int n;//声明一个在其他文件定义的外部变量n

对于外部函数,加不加 extern 效果都是一样的

如果在定义变量和函数时使用static关键字,可以让该变量和函数无法被其他编译单元引用

  • 动态内存分配

运算符new的功能是动态分配内存,语法形式为

new 数据类型(初始化参数列表)

对于基本数据类型,如果不希望在分配内存后设立初值,可以把括号省去

int* point = new int;

如果保留括号,但括号中不写任何数值,则表示用0来进行初始化

int* point = new int( );

运算符delete用来删除由new建立的对象,释放指针所指向的内存空间,格式为:

delete 指针名;

用new分配的内存,必须用delete加以释放,否则会造成“内存泄漏”,而且只用delete进行一次删除,对同一内存空间多次使用delete进行删除会导致运行错误

用new创建一维数组时,在方括号后加或者不加小括号的区别和“new T( )”一样,用delete删除时在指针名前面要加“[ ]”

int* p = new int[100]; //不设置初值
int *p = new int[100] ( ); //用0进行初始化
delete[ ] p;

  • 深复制与浅复制
    • 浅复制只是对指针的复制,复制后两个指针指向同一个内存空间;
    • 深复制不但对指针进行复制,而且对指针指向的内容进行复制,经深复制后的指针是指向两个不同地址的指针

默认复制构造函数,进行的是浅复制,对指针复制后会出现两个指针指向同一个内存空间的情况,内存空间会被析构函数释放两次,导致运行错误

解决这一问题必须要自己定义复制构造函数,使复制后的对象指针成员有自己的内存空间,即进行深复制,这样就避免了内存泄漏发生。

  • this指针
    • this指针是一个隐含于每一个类的非静态成员函数中的特殊指针,它用于指向正在被成员函数操作的对象
    • 当局部作用域中声明了与类成员同名的标识符时,对该标识符的直接引用代表的是局部作用域中所声明的标识符,这时为了访问该类成员,可以通过this指针

1

2

3

4

5

6

7

8

class A{

public:

    void display(int x){

        this->x=x;   //前一个x为数据成员,后一个x为形参

    }

private:

    int x;

};


版权声明 : 本文内容来源于互联网或用户自行发布贡献,该文观点仅代表原作者本人。本站仅提供信息存储空间服务和不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权, 违法违规的内容, 请发送邮件至2530232025#qq.cn(#换@)举报,一经查实,本站将立刻删除。
原文链接 : https://blog.csdn.net/qq_42582489/article/details/123449750
相关文章
  • C++中类的六大默认成员函数的介绍

    C++中类的六大默认成员函数的介绍
    一、类的默认成员函数 二、构造函数Date(形参列表) 构造函数主要完成初始化对象,相当于C语言阶段写的Init函数。 默认构造函数:无参的构
  • C/C++实现遍历文件夹最全方法总结介绍

    C/C++实现遍历文件夹最全方法总结介绍
    一、filesystem(推荐) 在c++17中,引入了文件系统,使用起来非常方便 在VS中,可以直接在项目属性中调整: 只要是C++17即以上都可 然后头文件
  • C语言实现手写Map(数组+链表+红黑树)的代码

    C语言实现手写Map(数组+链表+红黑树)的代码
    要求 需要准备数组集合(List) 数据结构 需要准备单向链表(Linked) 数据结构 需要准备红黑树(Rbtree)数据结构 需要准备红黑树和链表适配策略
  • MySQL系列教程之使用C语言来连接数据库

    MySQL系列教程之使用C语言来连接数据库
    写在前面 知道了 Java中使用 JDBC编程 来连接数据库了,但是使用 C语言 来连接数据库却总是连接不上去~ 立即安排一波使用 C语言连接 MySQL数
  • 基于C语言实现简单学生成绩管理系统

    基于C语言实现简单学生成绩管理系统
    一、系统主要功能 1、密码登录 2、输入数据 3、查询成绩 4、修改成绩 5、输出所有学生成绩 6、退出系统 二、代码实现 1 2 3 4 5 6 7 8 9 10 11
  • C语言实现共享单车管理系统

    C语言实现共享单车管理系统
    1.功能模块图; 2.各个模块详细的功能描述。 1.登陆:登陆分为用户登陆,管理员登陆以及维修员登录,登陆后不同的用户所执行的操作
  • C++继承与菱形继承的介绍

    C++继承与菱形继承的介绍
    继承的概念和定义 继承机制是面向对象程序设计的一种实现代码复用的重要手段,它允许程序员在保持原有类特性的基础上进行拓展,增加
  • C/C++指针介绍与使用介绍

    C/C++指针介绍与使用介绍
    什么是指针 C/C++语言拥有在程序运行时获得变量的地址和操作地址的能力,这种用来操作地址的特殊类型变量被称作指针。 翻译翻译什么
  • C++进程的创建和进程ID标识介绍
    进程的ID 进程的ID,可称为PID。它是进程的唯一标识,类似于我们的身份证号是唯一标识,因为名字可能会和其他人相同,生日可能会与其他
  • C++分析如何用虚析构与纯虚析构处理内存泄漏

    C++分析如何用虚析构与纯虚析构处理内存泄漏
    一、问题引入 使用多态时,如果有一些子类的成员开辟在堆区,那么在父类执行完毕释放后,没有办法去释放子类的内存,这样会导致内存
  • 本站所有内容来源于互联网或用户自行发布,本站仅提供信息存储空间服务,不拥有版权,不承担法律责任。如有侵犯您的权益,请您联系站长处理!
  • Copyright © 2017-2022 F11.CN All Rights Reserved. F11站长开发者网 版权所有 | 苏ICP备2022031554号-1 | 51LA统计