运维开发网

你知道c++的数据共享和保护吗

运维开发网 https://www.qedev.com 2022-10-29 18:39 出处:网络
这篇文章主要为大家详细介绍了C语言零基础入门的方法,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助

这篇文章主要为大家详细介绍了C语言零基础入门的方法,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助


1.作用域

作用域是程序体中标识符有效的区域。

从最大到最小的范围关系是:

命名空gt;之间的范围。班级范围gt;局部范围

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

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


2.对象生存期

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

局部生存期对象在声明点产生,并在执行声明所在的块时结束。

命名空间作用域中声明的对象都具有静态生存期定义时未指定初值的基本类型静态生存期变量,会被赋予0值初始化如果要在函数内部的局部作用域中声明具有静态生存期的对象,则要使用关键字staticvoid f(){static int m=0;//m仅在f中能访问 m++;coutlt;lt;mlt;lt;endl;}


静态数据成员

如果某个属性是整个类共有的,那么可以使用static关键字将其声明为静态成员。

静态成员在每个类中只有一个副本,由该类的所有对象共同维护和使用在类中不能对static静态数据成员进行初始化,要初始化必须在类外进行定义class A{public:static int m; };int A::m=20;//在类外进行初始化 int main(){A a,b;a.m=10; //可以赋值 coutlt;lt;a.mlt;lt;endl;coutlt;lt;b.mlt;lt;endl;//两者的值相同}


静态成员函数静态成员函数可以通过类名或对象名来进行调用,非静态成员函数只能通过对象名来调用静态成员函数可以直接访问该类的静态数据和函数成员,而访问非静态成员,必须通过对象名class A{public:static void f(A a);static void g(){coutlt;lt;"hello"lt;lt;endl;}void fun(){coutlt;lt;"world"lt;lt;endl;}private:int x;static int y;};int A::y=10;void A::f(A a){coutlt;lt;a.xlt;lt;endl; //必须通过对象名访问coutlt;lt;ylt;lt;endl; //直接访问该类的静态数据成员 g();//直接访问该类的静态成员函数 }int main(){A a;A::f(a); //直接通过类名调用return 0; }


3.类的友元

朋友关系是一种数据共享机制,通过这种机制,一个类中的公共函数或成员函数可以访问封装在另一个类中的数据。

为了保证数据的完整性和紧密性,建议尽量少用好友。


友元函数

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

class A{public:friend int main();private:int x;};int main(){A a;a.x=5;//访问 private对象 }


友元类

如果B类是A类的友元,那么B类的所有成员函数都是A类的友元函数,它们可以访问A类的私有和受保护成员。

class A{public:friend class B;private:int x,y;void f(){coutlt;lt;xlt;lt;endl;} };class B{public:void print(){a.x=5;a.y=10;coutlt;lt;a.ylt;lt;endl;//可以访问A类对象的私有成员 a.f();//可以访问A类对象的私有函数 }private:A a;};

注意(!!!)

1.朋友和朋友是单向的。

B类是a类的朋友。B类可以访问a类的私有数据,但a类不能访问B类的私有数据..

2.朋友和朋友是不能转让的。是B的朋友,C是B的朋友,如果没有声明,C和A之间不存在朋友关系。

3.朋友和朋友是不能继承的。


4.共享数据的保护


常对象

其成员值在对象的整个生命周期内不可修改的对象称为常量对象,一般用const修饰。

对象通常需要初始化,并且不能更新。

声明对象的语法形式是:

常量类型描述符对象名;

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关键字修饰的函数是常量成员函数。

语法:

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

如果一个对象被描述为常量对象,那么通过常量对象只能调用其常量成员函数,而不能调用其他函数(常量对象唯一的外部接口模式)。

class A{public:A(int i,int j):x(i),y(j){···}void print(){coutlt;lt;xlt;lt;" "lt;lt;ylt;lt;endl;}void print() const{//常成员函数coutlt;lt;xlt;lt;" const "lt;lt;ylt;lt;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描述的数据成员是常量数据成员。

类描述一个常量数据成员。任何函数都不能给它赋值,构造函数只能通过初始化列表来初始化它。

class A{public://常数据成员只能通过构造函数的初始化列表来获得初值 A(int i):a(i){···}private:const int a; //常数据成员static const int b;//静态常数据成员};const int A::b=10; //静态常数据成员在类外初始化


常引用

如果引用在声明时用const修饰,则声明的引用是正则引用,正则引用引用的对象不能更新。

经常引用的申报单:

常量类型说明符amp参考名称;

常量引用无论是绑定到普通对象还是常量对象,都只能在通过引用访问对象时被视为常量对象。

class Point{public:Point(int x,int y):x(x),y(y){}friend float dist(const Point amp;p1,const Point amp;p2);private:int x,y;};float dist(const Point amp;p1,const Point amp;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);coutlt;lt;dist(m1,m2)lt;lt;endl; //两点间距离 }


Tipsinclude书写方式include lt;文件名gt;,按照标准方式搜索嵌入文件,文件位于编译环境include子目录下。示例:include lt;iostreamgt;include ldquo;文件名rdquo;,在当前目录下搜索嵌入文件,如果搜不到则转为标准搜索。示例:include quot;point.hquot;外部变量如果一个变量可以在本文件和其他文件中使用,称为外部变量,用 extern 关键字说明

外部整数n;//声明在其他文件中定义的外部变量n

对于外部函数,无论有没有extern,效果都一样。

如果在定义变量和函数时使用static关键字,可以防止它们被其他编译单元引用。

动态内存分配

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

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

对于基本数据类型,如果不想在内存分配后设置初始值,可以省略括号。

int * point = new int

如果您保留括号,但不在其中写入任何值,这意味着0用于初始化。

int * point = new int();

delete操作符用于删除new创建的对象,释放指针指向的内存空。格式是:

删除指针名称;

new分配的内存必须通过delete释放,否则会造成ldquo内存泄漏rdquo,并且只删除一次。多次删除同一个内存空会导致运行错误。

用new创建一维数组时,方括号和ldquo后加不加括号的区别;新T()rdquo;同样,用delete删除时在指针名称前加ldquo[]rdquo;

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

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

默认的复制构造函数是浅层复制。复制完指针后,两个指针会指向同一个内存空,内存空会被析构函数释放两次,导致运行错误。

要解决这个问题,必须自己定义复制构造函数,让被复制的对象指针成员有自己的内存空,即深度复制,从而避免内存泄漏。

this指针this指针是一个隐含于每一个类的非静态成员函数中的特殊指针,它用于指向正在被成员函数操作的对象当局部作用域中声明了与类成员同名的标识符时,对该标识符的直接引用代表的是局部作用域中所声明的标识符,这时为了访问该类成员,可以通过this指针class A{public:void display(int x){this-gt;x=x; //前一个x为数据成员,后一个x为形参}private: int x;};


总结

本文到此为止。希望能帮到你

0

精彩评论

暂无评论...
验证码 换一张
取 消