艺术考试网
全国站

C++ 中 static 修饰符的作用、引入原因及使用场景解析

chanong
2024-06-10 04:52:14
编辑说
1、什么是static? static是C++中很常用的修饰符,它被用来控制变量的存储方式和可见性。2、为什么要引入static?

1. 什么是 ?

它是C++中非常常用的修饰符,用于控制变量的存储方式和可见性。

2.为什么要引入它?

当程序执行到函数内部定义的变量的定义时,编译器会为其分配栈上的空间。众所周知,一个函数在栈上分配的空间,会在函数结束时释放。这样就带来一个问题:如果想在函数中保存这个变量的值,直到下一次调用,该如何实现呢?最容易想到的办法就是定义一个全局变量,但是定义成全局变量有很多缺点,最明显的就是破坏了这个变量的访问作用域(使得在这个函数中定义的变量不只受这个函数控制)。

3.何时使用?

要求一个数据对象服务于整个类而不是某个对象,同时力求不破坏类的封装性,即要求这个成员隐藏在类内部,对外不可见。

4.内部机制:

静态数据成员在程序开始运行时必须存在。由于函数是在程序执行期间调用的,因此静态数据成员不能在任何函数中分配空间并初始化。

这样,它的空间分配可能存在三个地方,第一是作为类的外部接口的头文件,这里有类的声明;第二是类定义的内部实现,这里有类的成员函数定义;第三是应用程序的main()函数之前的全局数据声明与定义。

静态数据成员需要分配空间,所以不能在类声明中定义(只能​​声明数据成员)。类声明只声明类的“大小和规格”,并不执行实际的内存分配,所以在类声明中写定义是错误的。它也不能在头文件中的类声明之外定义,因为那会导致它在使用该类的多个源文件中被重复定义。

引入是为了告诉编译器将变量存储在程序的静态存储区中,而不是存储在堆栈上。

数据成员按定义顺序初始化。静态成员嵌套时,必须初始化嵌套的成员。消除顺序是初始化的逆序。

5.优点:

由于静态数据成员是所有对象共用的,因此可以节省内存。因此,对于多个对象来说,静态数据成员只存储在一个地方,供所有对象共享。静态数据成员的值对于每个对象都是相同的,但是其值可以更新。只要静态数据成员的值更新一次,就可以保证所有对象访问相同的更新值,这样可以提高时间效率。

6.引用静态数据成员时,使用以下格式:

::

如果静态数据成员的访问权限允许(即的成员),则可以按照上述格式在程序中引用该静态数据成员。

7.注意事项:

(1)类的静态成员函数属于整个类,而不是类对象,所以它没有this指针,也就是说它只能访问类的静态数据和静态成员函数。

(2)静态成员函数不能定义为虚函数。

(3)由于静态成员是在类内声明,在类外进行操作,所以对静态成员的地址操作有些特殊,变量地址是指向其数据类型的指针,函数地址类型则是“函数指针”。

(4)由于静态成员函数没有 this 指针,所以它们几乎等同于函数。这带来了一个意想不到的好处:通过成为函数,我们可以将 C++ 和基于 C 的 X 系统结合起来,也可以成功应用于线程函数。

(5)不会增加程序的时间和空间开销,相反,缩短了子类访问父类静态成员的时间,节省了子类的内存空间。

(6)静态数据成员前面带有关键字。

(7)静态数据成员是静态存储的,因此必须初始化。

(8)静态成员初始化与一般数据成员初始化不同:

初始化在类体外部进行,不加前缀,避免与一般的静态变量或对象混淆;

初始化时没有添加成员的访问控制符号等。

初始化时使用作用域运算符,标明所属的类;

因此我们得到静态数据成员初始化的格式:

::=

(9)为了防止父类的影响,可以在子类中定义一个和父类相同的静态变量,以屏蔽父类的影响。这里有一点需要注意:我们说静态成员是父类和子类共享的,但是我们却重复定义了静态成员。这会不会出错呢?不会的,我们的编译器用了一个巧妙的技巧:name-来生成一个唯一的标识符。

静态数据成员

在类中,静态成员可以实现多个对象之间的数据共享,而且静态数据成员的使用不违背隐藏原则,也就是保证了安全性。因此,静态成员是类的所有对象共享的成员,而不是某一个对象的成员。

使用静态数据成员可以节省内存,因为它们是所有对象所共有的。因此,对于多个对象,静态数据成员只存储在一个地方供所有对象共享。静态数据成员的值对于每个对象都是相同的,但其值可以更新。只要静态数据成员的值更新一次,就可以保证所有对象访问相同的更新值,这可以提高时间效率。

静态数据成员的使用及注意事项如下:

1.在静态数据成员的定义或者说明前添加关键字。

2、静态成员初始化与一般的数据成员初始化不同,静态数据成员初始化的格式如下:

::=

这表明:

(1)初始化在类体之外进行,无需在声明之前进行,以避免与一般的静态变量或对象混淆。

(2)初始化时没有添加该成员的访问权限控制符号等。

(3)初始化时使用作用域运算符,标明所属的类。因此,静态数据成员是类的成员,而不是对象的成员。

3.静态数据成员静态存储,具有静态生存期,并且必须初始化。

4.引用静态数据成员时,使用以下格式:

::

如果静态数据成员的访问权限允许(即的成员),则可以按照上述格式在程序中引用该静态数据成员。

静态成员函数

静态成员函数与静态数据成员相同,都是类的静态成员,不是对象成员,因此对静态成员的引用不需要使用对象名。

在静态成员函数的实现中,不能直接引用类中描述的非静态成员,但可以引用类中描述的静态成员。如果要在静态成员函数中引用非静态成员,可以通过对象来引用。

让我们看一个例子:

#

点类

空白 ()

无效初始化()

};

无效主要(无效)

点 pt;

pt.初始化();

點。();

这将能够顺利编译而不会出现任何错误。

以此方式看待

#

点类

空白 ()

无效初始化()

};

无效主要(无效)

观点::();

这会导致编译错误,并出现错误消息: call of non- ,为什么?

因为当一个类的具体对象没有被实例化时,该类是不会分配内存空间的。

好的,我们来看下面的例子:

#

点类

空白 ()

无效初始化()

};

无效主要(无效)

点::初始化();

此时不会出现编译错误,因为类在定义的时候c语言static,它的静态数据和成员函数都有自己的内存区域,不属于类的任何一个具体的对象。

好的,我们来看下面的例子:

#

点类

空白 ()

无效初始化()

x = 0;

y = 0;

int x;

int y;

};

无效主要(无效)

点::初始化();

编译错误:

到数据 ''Point::x''

到数据 ''Point::y''

在静态成员函数中错误地引用数据成员。

还是同样的问题,静态成员(函数)不属于任何具体的对象,所以在类的具体对象声明之前已经有了内存区域,现在非静态数据成员还没有分配内存空间,所以这里的调用是错误的,就如同没有声明就提前使用了一个变量一样。

也就是说非静态成员变量不能被静态成员函数引用。

好的,我们来看下面的例子:

#

点类

空白 ()

x = 0;

y = 0;

在里面();

无效初始化()

int x;

int y;

};

无效主要(无效)

点::初始化();

好的,所以不会有任何错误。这最终是一个内存模型的问题,

任何变量只有在内存中拥有自己的空间之后才可以被其他地方调用,否则就会出现错误。

好的,我们来看下面的例子:

#

点类

空白 ()

无效初始化()

x = 0;

y = 0;

int x;

int y;

};

无效主要(无效)

点::初始化();

编译:

...

test.obj:错误:“:int Point::y”

test.obj:错误:“:int Point::x”

Debug/Test.exe:致命错误:2

执行 link.exe 时发生错误。

可以看到编译没有错误,但是连接有错误,这是为什么呢?

这是因为静态成员变量需要初始化,可以这样做:

#

点类

空白 ()

无效初始化()

x = 0;

y = 0;

int x;

int y;

};

int 点::x = 0;

int 点::y = 0;

无效主要(无效)

点::初始化();

静态成员数据变量初始化后不会发生编译错误。

看一下下面的代码:

#

点类

空白 ()

无效初始化()

x = 0;

y = 0;

int x;

int y;

};

无效主要(无效)

编译的时候没有错误,为什么?

即使它们没有初始化,由于我们无法访问 x、y,所以编译不会失败。

C++ 区分两种类型的成员函数:静态成员函数和非静态成员函数。两者之间的主要区别在于静态成员函数不接受隐式 this 参数。因此,它们无法访问其自身类的非静态成员。

在某些情况下,例如使用多线程库(不支持类)时,必须使用静态成员函数,因为它们的地址与 C 函数的地址兼容。此限制迫使程序员使用各种解决方法从静态成员函数访问非静态数据成员。

第一个解决方案是将类的所有数据成员声明为静态的。这样,静态成员函数就可以直接访问它们,例如:

班级

*();

*p;

锁锁;

};

* ::()

lock.(); // 很好,锁是

如果 (!p)

p=新的;

锁。();

磷;

对于需要使用非静态数据成员的类,此解决方法不起作用。

访问非静态数据成员

传递对相关对象的引用允许静态成员函数访问该对象的非静态数据:

A 类

无效函数(A&obj);

()常量; //非-

};

静态成员函数func()使用引用obj来访问非静态成员val。

voidA::func(A&obj)

int n = obj.();

将引用或指针作为参数传递给静态成员函数模仿自动将 this 参数传递给非静态成员函数的行为。

免责声明
本站所有收录的学校、专业及发布的图片、内容,均收集整理自互联网,仅用于信息展示,不作为择校或选择专业的建议,若有侵权请联系删除!

大家都在看

圆的面积计算公式课堂实录:探索数学与生活的联系

圆的面积计算公式课堂实录:探索数学与生活的联系

圆的面积计算公式.doc圆的面积计算公式《圆的面积计算公式》课堂实录教学目标:知识与技能:掌握圆的面积计算公式,并能正确计算圆的面积。
2024-06-10
C++ 中 static 修饰符的作用、引入原因及使用场景解析

C++ 中 static 修饰符的作用、引入原因及使用场景解析

1、什么是static? static是C++中很常用的修饰符,它被用来控制变量的存储方式和可见性。2、为什么要引入static?
2024-06-10
工商管理专业介绍与考试科目全解析

工商管理专业介绍与考试科目全解析

工商管理——专业介绍:工商管理是研究工商企业经济管理基本理论和一般方法的学科,主要包括企业的经营战略制定和内部行为管理两个方面。
2024-06-10
湖南省教师资格证考试认定公告详细信息

湖南省教师资格证考试认定公告详细信息

关于2023年上半年湖南郴州市高中(中职)教师资格认定有关事项的公告,湖南教师资格为大家带来相关认定公告详细信息如下:
2024-06-10
008 工商管理学院:完备人才培养体系,一流本科专业建设

008 工商管理学院:完备人才培养体系,一流本科专业建设

专业基本概况所属院系所属院系及代码:008工商管理学院学院拥有完备的本硕博人才培养体系,设有工商管理一级学科博士点下的企业管理、技术经济及管理两
2024-06-10
2023 年下半年中小学教师资格考试(笔试)上海考区报名公告

2023 年下半年中小学教师资格考试(笔试)上海考区报名公告

据教育部、教育部教育考试院统一部署和上海市教育委员会有关文件精神
2024-06-10
计算机和 PLC 编程中变量的概念及静态变量的介绍

计算机和 PLC 编程中变量的概念及静态变量的介绍

我最早接触“静态变量”的概念是在计算机C语言的编程中,清楚的记得它需要用"static"关键字来声明。
2024-06-10
甘肃 2023 年上半年中小学教师资格考试(笔试)报名时间及条件

甘肃 2023 年上半年中小学教师资格考试(笔试)报名时间及条件

甘肃2023年上半年中小学教师资格考试(笔试)报名时间已经发布,报名时间是在1月13-16日17时。中小学教师资格考试(笔试)报名审核时间是在1月13-17日17时。
2024-06-10
2021 年山东省高考工作新闻发布会,各项准备工作有序推进

2021 年山东省高考工作新闻发布会,各项准备工作有序推进

临沂教育发布 临沂市教育局唯一官方 关注 4月19日,山东省教育厅举行“2021年高考工作新闻发布会”,省委教育工委委员、省教育厅党组成员、副厅长戴龙成,省公安
2024-06-10
湖北师范大学是几本?招生批次、学校介绍全知道

湖北师范大学是几本?招生批次、学校介绍全知道

湖北师范大学在湖北既有第一批次招生也有第二批次招生,所以严格意义上,通常说湖北师范大学是二本大学,如果全部在第一批次招生,我们通常才说湖北师范大学是一本大学。如果你不是湖北考生
2024-06-10