C++从入门到精通——static成员

server/2024/9/25 23:12:29/

static成员

  • 前言
  • 一、static成员
    • 概念
    • 例题
  • 二、 static成员的特性
    • 特性
    • 例题
      • 静态成员函数可以调用非静态成员函数吗
      • 非静态成员函数可以调用类的静态成员函数吗
  • 三、static成员的注意事项
    • static不能给缺省值
    • static修饰变量和修饰函数的区别
      • 静态变量(static variable):
      • 静态函数(static function):
      • 示例
      • 总结
  • 四、练习题


前言


一、static成员

概念

声明为static的类成员称为类的静态成员,用static修饰的成员变量,称之为静态成员变量;用static修饰的成员函数,称之为静态成员函数。静态成员变量一定要在类外进行初始化。

静态成员是指属于类而不属于类的任何对象的成员。静态成员在类的所有对象之间共享,并且可以在不创建对象的情况下被访问。静态成员包括静态变量和静态方法。

静态变量是类的所有对象之间共享的变量。它们在内存中只有一份拷贝,并且可以直接通过类名访问。静态变量在类的任何对象被创建之前就被初始化,它们的值在所有对象之间是一致的。

静态方法是属于类而不属于任何对象的方法。它们可以直接通过类名调用,而不需要创建类的对象。静态方法通常用于执行与类相关的操作,而不涉及特定对象的状态。

静态成员在类的定义中使用static关键字进行声明。例如,以下是一个使用静态变量和静态方法的示例:

class MyClass {
public:static int staticVar; // 静态变量声明static void staticMethod(); // 静态方法声明
};int MyClass::staticVar = 0; // 静态变量定义和初始化void MyClass::staticMethod() {// 静态方法的实现cout << "This is a static method." << endl;
}int main() {MyClass::staticVar = 10; // 静态变量的访问MyClass::staticMethod(); // 静态方法的调用return 0;
}

在上述示例中,静态变量staticVar和静态方法staticMethod属于类MyClass,可以直接通过类名进行访问和调用。

例题

实现一个类,计算程序中创建出了多少个类对象。

class A
{
public:A() { ++_scount; }A(const A& t) { ++_scount; }~A() { --_scount; }static int GetACount() { return _scount; }
private:static int _scount;
};int A::_scount = 0;void TestA()
{cout << A::GetACount() << endl;A a1, a2;A a3(a1);cout << A::GetACount() << endl;
}

以上代码定义了一个名为A的类,该类包含一个私有的静态成员变量_scount,一个默认构造函数,一个拷贝构造函数和一个析构函数。在main函数中,调用TestA函数。

TestA函数中,首先调用A::GetACount()函数获取当前A类的对象数量,然后创建了两个A类的对象a1a2,并将a1传递给a3的拷贝构造函数。再次调用A::GetACount()函数获取当前A类的对象数量。

_scount是一个静态成员变量,它在类定义外进行初始化,并在类定义中被声明为私有。该变量用于记录A类的对象数量。默认构造函数和拷贝构造函数都会在对象创建时将_scount自增1,析构函数会在对象销毁时将_scount自减1。

因此,输出结果将显示A类对象的数量。首先是0,因为还没有创建任何A类的对象。然后是3,因为在TestA函数中创建了两个对象(a1a2),并进行了一次拷贝构造(a3)。最后,在TestA函数结束后,对象被销毁,_scount减少到0。

二、 static成员的特性

特性

  1. 静态成员为所有类对象所共享,不属于某个具体的对象,存放在静态区
  2. 静态成员变量必须在类外定义,定义时不添加static关键字,类中只是声明
  3. 类静态成员即可用 类名::静态成员 或者 对象.静态成员 来访问
  4. 静态成员函数没有隐藏的this指针,不能访问任何非静态成员
  5. 静态成员也是类的成员,受publicprotectedprivate 访问限定符的限制

例题

静态成员函数可以调用非静态成员函数吗

静态成员函数可以调用非静态成员函数,但需要通过对象或者指针来调用。因为非静态成员函数是依赖于具体的对象或者实例的,而静态成员函数是独立于对象或者实例的,所以在静态成员函数中不能直接访问非静态成员变量和非静态成员函数。但可以通过将对象作为参数传递进来或者通过对象指针来调用非静态成员函数。

非静态成员函数可以调用类的静态成员函数吗

非静态成员函数可以调用类的静态成员函数。在非静态成员函数中,可以使用类名和作用域解析操作符(::)来调用静态成员函数。

三、static成员的注意事项

static不能给缺省值

在这里插入图片描述
在C++中,static关键字用于声明静态成员变量或静态函数。在声明静态成员变量时,不能直接为其设置缺省值。

其中一个原因是缺省值是要走初始化列表的,而static是不会走初始化列表。

除此之外,因为静态成员变量在编译阶段就已经被分配了内存空间(即在静态区),并没有被放置在对象的内存空间中。静态成员变量是属于整个类而不是某个具体对象的,它的生命周期独立于任何对象的创建和销毁。

如果允许为静态成员变量设置缺省值,那么在编译阶段就需要为所有的静态成员变量分配空间并为其赋值。这将引入额外的开销和复杂性,因为静态成员变量的初始值可能会依赖于其他静态成员变量或静态函数的结果。

为了避免这种复杂性和性能开销,C++规定了静态成员变量不能直接设置缺省值。可以在类外部定义静态成员变量,并在类外部进行初始化赋值:

class MyClass {static int myStaticVariable;
};int MyClass::myStaticVariable = 0; // 在类外部进行初始化赋值

需要注意的是,如果不在类外部进行初始化赋值,静态成员变量的初始值将是未定义的。因此,为了保证静态成员变量的可靠性,最好在类外部进行初始化赋值。

static修饰变量和修饰函数的区别

C++中,static关键字可以用于修饰变量和函数,并且在两者之间有一些区别。

静态变量(static variable):

  • 静态变量被存储在静态存储区,其生命周期延长至整个程序的运行期间。
  • 静态变量只在声明它的作用域内可见,不能被其他文件访问。
  • 静态变量的初始化只会在程序第一次进入声明它的作用域时执行一次,并且只能在声明时给定初值。
  • 静态变量的作用域限制在声明它的函数或类中,但它的值在函数调用之间保持保持不变。

静态函数(static function):

  • 静态函数属于类而不是对象,它可以直接通过类名调用,无需创建对象实例。
  • 静态函数没有this指针,因此无法访问非静态成员变量或成员函数。
  • 静态函数只能直接访问静态成员变量或调用其他静态函数。

示例

当我们在C++中定义了一个静态函数后,可以通过以下方式进行调用:

#include <iostream>class MyClass {
public:static void staticFunction() {std::cout << "This is a static function." << std::endl;}
};int main() {// 通过类名直接调用静态函数MyClass::staticFunction();return 0;
}

在上面的例子中,我们定义了一个名为MyClass的类,并在该类中声明了一个静态函数staticFunction。在main函数中,我们通过类名MyClass::staticFunction()的方式直接进行调用。

输出结果将会是"This is a static function."

需要注意的是,因为静态函数不依赖于对象实例,所以可以通过类名直接访问。而不需要先创建对象实例。

总结

  • 静态变量的生命周期长,作用域限制在声明它的作用域内,值在函数调用之间保持不变。
  • 静态函数属于类而不是对象,无需创建对象实例,只能访问静态成员变量和调用其他静态函数。

四、练习题

提示:使用本文所提到的静态函数和静态变量来解决

JZ64 求1+2+3+…+n



http://www.ppmy.cn/server/7345.html

相关文章

二极管分类及用途

二极管分类及用途 通用开关二极管 特点&#xff1a;电流小&#xff0c;工作频率高 选型依据&#xff1a;正向电流、正向压降、功耗&#xff0c;反向最大电压&#xff0c;反向恢复时间&#xff0c;封装等 类型&#xff1a;BAS316 ; IN4148WS 应用电路: 说明&#xff1a;应用…

23.组件注册方式

组件注册方式 一个 Vue 组件在使用前需要先被“注册”&#xff0c;这样 Vue 才能在渲染模板时找到其对应的实现。组件注册有两种方式&#xff1a;全局注册和局部注册 全局注册 import { createApp } from vue import App from ./App.vue import GlobalComponent from ".…

vulfocus靶场redis 未授权访问漏洞之CNVD-2015-07557

目标系统的权限不够redis用户无法写计划任务和公钥&#xff0c;而且也没有开放ssh端口。 主从复制getshell&#xff0c;写入恶意的so文件达到执行系统命令的目的。 github上有一键可以利用的脚本 https://github.com/n0b0dyCN/redis-rogue-server.git 利用条件&#xff1a;需…

利用SD-WAN技术优化企业网络

随着全球化进程不断加速&#xff0c;企业面临着越来越多的网络挑战和需求。特别是在分布于不同地区的分支机构之间建立稳定、高效的网络连接&#xff0c;是许多企业迫切需要解决的问题。在这一背景下&#xff0c;SD-WAN技术的出现为企业网络优化带来了全新的解决方案。 SD-WAN专…

Unity类银河恶魔城学习记录13-1 p142 Save system源代码

Alex教程每一P的教程原代码加上我自己的理解初步理解写的注释&#xff0c;可供学习Alex教程的人参考 此代码仅为较上一P有所改变的代码 【Unity教程】从0编程制作类银河恶魔城游戏_哔哩哔哩_bilibili FileDataHandler.cs using System; using System.IO; using UnityEngine; p…

RabbitMQ-交换机

文章目录 交换机fanoutDirecttopicHeadersRPC 交换机 **交换机 **是消息队列中的一个组件&#xff0c;其作用类似于网络路由器。它负责将我们发送的消息转发到相应的目标&#xff0c;就像快递站将快递发送到对应的站点&#xff0c;或者网络路由器将网络请求转发到相应的服务器…

色彩的魔力:渐变色在设计中的无限可能性

夕阳&#xff0c;天空&#xff0c;湖面&#xff0c;夕阳...随着距离和光影的变化&#xff0c;颜色的渐变色&#xff0c;近大远小、近实远虚的透视&#xff0c;为大自然营造了浪漫的氛围。延伸到UI/UX设计领域&#xff0c;这种现实、惊艳、独特的渐变色也深受众多设计师的喜爱。…

引用静态方法

import java.util.Arrays; import java.util.Comparator;public class demo1 {//引用public static void main(String[] args) {Integer []arr{1,2,4,3,8,6};//匿名内部类Arrays.sort(arr, new Comparator<Integer>() {Overridepublic int compare(Integer o1, Integer o…