当前位置: 首页 > news >正文

C++(2)(数据的共享与保护)

作用域:

1.局部作用域:

       形参列表中形参的作用域:从声明处开始,到整个函数体结束为止(也就是右大括号})函数体内声明的变量同理,也是从从声明处开始,到整个函数体结束为止。

-->具有局部作用域的变量成为局部变量

2.类作用域:

       类可以被看成是一组有名成员的集合,类X的成员m具有类作用域,
       对m的访问方式有如下3种:
       (1)如果在X的成员函数中没有声明同名的局部作用域标识符,那么在该函数内可以直接访问成员m。也就是说m在这样的函数中都起作用。

class X {
public:int m; // 类的成员变量void memberFunction() {m = 10; // 直接访问成员变量m// 在这里,m引用的是类的成员变量,因为没有同名的局部变量}void anotherFunction() {int m; // 局部变量mm = 20; // 这里的m引用的是局部变量// 如果要访问类的成员变量m,需要使用this指针this->m = 30; // 使用this指针来明确引用类的成员变量}
};

       在memberFunction中,由于没有声明同名的局部变量,可以直接使用m来引用类的成员变量。而在anotherFunction中,由于存在一个同名的局部变量m,因此直接使用m会引用局部变量。
如果要引用类的成员变量,需要使用this->m来明确指出(this指针是一个指向当前对象的指针,它允许你访问该对象的成员变量和成员函数。在非静态成员函数中,this指针是隐含存在的,即使你没有显式地使用它。)。
    (2)通过表达式x. m或者X::m。这正是程序中访问对象成员的最基本方法。X.:m的方式一般用于访问类的静态成员。
    (3)通过ptr一>m这样的表达式,其中 ptr为指向X类的一个对象的指针。

3.命名空间作用域

 为了消除不同模块的类和函数之间由于重名引发的错误,所以创造了命名空间。实际上就是为了区分:成都的解放路和南京的解放路,消除歧义。

 命名空间语法形式:

 namespace命名空间名{
 命名空间内的各种声明(函数声明、类声明、……)
 }

引用其他命名空间类名或函数名:命名空间名::标识符名

someNs :: SomeClass objl ;
//声明一个SomeNs : : someclass型的对象obj1

使用命名空间:两种方法

1.using命名空间名::标识符名;

2.using namespace命名空间名;(使用cout:using namespace std)

       前一种形式将指定的标识符暴露在当前的作用域内,使得在当前作用域中可以直接引用该标识符;后一种形式将指定命名空间内的所有标识符暴露在当前的作用域内,使得在当前作用域中可以直接引用该命名空间内的任何标识符。

特殊的命名空间:全局命名空间和匿名命名空间

      全局命名空间实际上就是程序的全局作用域内的所有名称(除显式声明的命名空间之外,也就是没起名字,作用在全局作用域之内,就在全局命名空间内)

     匿名命名空间尝尝用来屏蔽不希望暴露给其他源文件的标识符,该作用域内的名称只在定义它们的源文件中可见,而不需要在头文件中进行声明。(本文件中调用时直接拿名字即可,不需要::,有点类似于static)

匿名对象:

       在C++中,匿名对象是指那些没有名字的对象,它们通常是通过临时表达式创建的。这些临时对象在它们的生命周期内(一般是调用的表达式)是有效的,但在表达式结束时就会被销毁。

       匿名对象通常不提供名称,因此它们无法被外部访问。这主要是因为它们是临时的,而且没有显式的名称来引用它们。匿名对象通常用于构造函数、函数参数、返回值、表达式等,它们在生命周期结束时就会被销毁。

      需要注意的是,匿名对象在使用时位const属性,也就是说,下列语句会报错:

Clock &ref = Clock(10,20,30);

做法:

左值引用,并且加入const:

const Clock &ref = Clock(10,20,30);

右值引用(上式的一种优化,因为const 左值显然没有意义):

Clock &&ref = Clock(10,20,30);

注意以下代码:

int &&ref = 10;
ref = 100;
cout << ref << endl;

      此时输出为100,但是显然10是一个常量,更确切的说是一个匿名对象,显然其时只读的,但是ref的输出变为了100,这意味着ref在栈区另外开辟了一个变量,其值为100,而此时10

对象的生存期与可见性:

可见性:

     可见性其实就是小的作用域可以屏蔽大的作用域中的同名变量,这点与C语言相似

生存期:

静态生存期:如果对象的生存期与程序的运行期相同,则称它具有静态生存期。(也就是static修饰的变量以及全局变量)

动态生存期:诞生于声明点,结束于块执行完毕之时

类的静态成员:

        类属性是描述类的所有对象共同特征的一个数据项,对于任何对象实例,它的属性值是相同的。举个例子,就像一个公司的名字,无论来几个员工,它都是一样的,且只有一份(意味着它是static),这时,它的生存期变为了静态生存期,

静态数据成员:

        此时,由于静态数据成员不属于任何一个对象,类名::标识符,--->在类的定义中只进行声明,而在使用时进行类名限定定义性声明(由于未分配对象时没有空间,所以要额外定义,通过其静态生命周期来推断出其应该使用全局变量的方式来定义,且此时不需要static修饰)

class SingelTon
{
public:static SingelTon *getIntance(){if(m_p == NULL){m_p = new SingelTon;}return m_p;}static void destroyIntance(){delete m_p;m_p = NULL;}static int getCounter(){return counter;}private:SingelTon(){++counter;}SingelTon(const SingelTon &){}~SingelTon(){--counter;}static SingelTon *m_p; //声明static int counter;
};SingelTon *SingelTon::m_p = NULL;  //限定性声明  
int SingelTon::counter = 0;

静态函数成员:

   与数据成员相似,只有一份,静态生存期,可以直接通过类名调用,但是:

   1.无this指针:静态成员函数内部没有this指针,这意味着它们不能直接访问非静态成员变量或非静态成员函数。

   2.不能访问非静态成员:由于没有this指针,静态成员函数不能直接访问非静态成员变量或非静态成员函数。如果需要访问这些成员,可以通过类名或对象名来访问。

int main () {Point : : showCount () ;/直接通过类名调用函数,输出对象个数的初始值Point a (4,5);cout<< "Point A,"<<a.getx ()<<","<<a.getY ();a.showCount ( ) ;Point b (a) ;cout<< "Point B, "<<b.getx ( )<<","<<b.getY () ;B.showcount ( ) ;
}

常对象:

    常对象必须进行初始化,且在整个生存周期内不能被更新

    const 类型说明符 对象名

const int n= 10;
//正确,用10对常量n进行初始化
n= 20;
//错误,不能对常量赋值

const修饰的类成员:

1.常成员函数

使用const关键字修饰的函数为常成员函数﹐常成员函数声明的格式如下:

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

注:

1.const是函数类型的一个组成部分,所以不论声明还是定义都需要加上const

2.如果一个对象是常对象,那么该常对象只能调用其常成员函数,而不能调用其他的成员函数

3.无论是否通过常对象调用,目的对象都视为常对象,因此常成员函数不能更新目的对象的数据成员,也不能调用没有用const修饰的成员函数

4.const函数可以用于重载函数的区分:

常对象调用常成员函数

非const的对象一般调用不用const修饰的成员函数        

2.常数据成员

常数据成员只能通过初始化列表来进行初始化

而静态成员要在类外说明以及初始化

3.常引用

  在声明引用时使用const修饰,那么此时声明的引用就是常引用。-->常引用的对象不能被更新

  声明形式:const 类型说明符 & 对象名;

  const引用后,其在参数传递时可以传递常对象

  需要注意的是,const不仅可以引用常对象,也可以引用普通对象,而在引用普通对象时,将这个普通对象当做常对象

 在实际使用时,如果不需要对实参进行更改,使用常引用可以避免意外对实参修改

class 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 &p1,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 static_cast<float> (sqrt(x*x + y*y));
}

友元函数与友元类:

友元函数:

   友元函数是在类中运用关键字friend修饰的非成员函数,但是在其函数体中可以通过对象名访问类的私有或保护成员

   也就是相当于:有一个函数void test()(不在类内),只要在类内声明friend void test();,那么此时该函数可以访问器私有或保护成员

class 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 &p1,Point &p2);//友元函数声明
private:int x,y;};float dist (Point &p1,Point &p2)
{//友元函数实现double x = p1.x - p2.x;//通过对象访问私有数据成员double y = p1.y - p2.y;return static_cast<float> (sqrt(x*x + y*y));
}

友元类:

         同友元函数一样若A类为B类的友元类,则A类的所有成员函数都是B类的友元函数﹐都可以访问B类的私有和保护成员。语法形式:

class B{//B类的成员声明……friend class A;……//声明A为B的友元类
};

注:

      1.友元关系是不能被传递的,B类是A类的友元类,C类是B类的友元类,但是C类并不是A类的友元类

      2.友元关系是单向的,B类是A类的友元,B类可以访问A类的私有或保护数据,但是A类不能访问B类的私有或保护数据

      3.友元关系不能被继承,也就是B的派生类不能继承B的友元。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • Go语言入门
  • Linux安全与高级应用(四)深入探索MySQL数据库:安装、管理与安全实践
  • Journyx项目管理软件 soap_cgi.pyc XXE漏洞复现
  • 【限流与Sentinel超详细分析】
  • 4.8.双向循环神经网络
  • 【C++综合项目】——基于Boost库的搜索引擎(手把手讲解,小白一看就会!!)
  • 前端web开发HTML+CSS3+移动web(0基础,超详细)——第4天
  • priority_queue模拟实现【C++】
  • FFmpeg源码:av_realloc、av_reallocp、size_mult、av_realloc_f函数分析
  • Springboot 开发之 Quartz 任务调度框架简介
  • 自定义View-- wifi强度
  • 从0开始搭建vue + flask 旅游景点数据分析系统( 六):搭建后端flask框架
  • Win32注册表操作
  • Rust 所有权
  • 大数据-Big Data(一):概述与基础
  • GitUp, 你不可错过的秀外慧中的git工具
  • IndexedDB
  • Laravel 中的一个后期静态绑定
  • leetcode386. Lexicographical Numbers
  • ng6--错误信息小结(持续更新)
  • niucms就是以城市为分割单位,在上面 小区/乡村/同城论坛+58+团购
  • nodejs:开发并发布一个nodejs包
  • 百度地图API标注+时间轴组件
  • 京东美团研发面经
  • 前端知识点整理(待续)
  • 如何解决微信端直接跳WAP端
  • 为物联网而生:高性能时间序列数据库HiTSDB商业化首发!
  • 小程序、APP Store 需要的 SSL 证书是个什么东西?
  • 再谈express与koa的对比
  • 怎么将电脑中的声音录制成WAV格式
  • ​Python 3 新特性:类型注解
  • #define MODIFY_REG(REG, CLEARMASK, SETMASK)
  • #git 撤消对文件的更改
  • $con= MySQL有关填空题_2015年计算机二级考试《MySQL》提高练习题(10)
  • ( 10 )MySQL中的外键
  • (1)Map集合 (2)异常机制 (3)File类 (4)I/O流
  • (LeetCode 49)Anagrams
  • (Repost) Getting Genode with TrustZone on the i.MX
  • (大众金融)SQL server面试题(1)-总销售量最少的3个型号的车及其总销售量
  • (十)DDRC架构组成、效率Efficiency及功能实现
  • (四) 虚拟摄像头vivi体验
  • (转)shell调试方法
  • (自用)网络编程
  • (最全解法)输入一个整数,输出该数二进制表示中1的个数。
  • ***详解账号泄露:全球约1亿用户已泄露
  • .\OBJ\test1.axf: Error: L6230W: Ignoring --entry command. Cannot find argumen 'Reset_Handler'
  • .bat批处理(五):遍历指定目录下资源文件并更新
  • .htaccess配置常用技巧
  • .net core 控制台应用程序读取配置文件app.config
  • .NET Core 中的路径问题
  • .NET 解决重复提交问题
  • .Net 应用中使用dot trace进行性能诊断
  • .net 重复调用webservice_Java RMI 远程调用详解,优劣势说明
  • .NET 自定义中间件 判断是否存在 AllowAnonymousAttribute 特性 来判断是否需要身份验证
  • .NET国产化改造探索(三)、银河麒麟安装.NET 8环境