c++关键字static

1. 静态成员变量和函数并不依赖于类的任何对象,它们是类的属性,因此不需要通过类的对象访问,可以通过类名直接访问。

2. 静态成员变量和函数是公有的,可被所有对象访问,但是无法访问类的非静态成员。

3. 静态成员变量和函数不能被声明为constvolatile或者constexpr

4. 静态成员变量必须在类外进行定义,且只能定义一次。

5. 静态成员函数不能直接访问类的非静态成员,静态成员函数及其参数中不允许使用this指针,因为this指针只有实例化后才会产生。

6. 静态成员函数不能被声明为虚函数,因为虚函数实现需要运行时的信息,而静态成员函数不依赖于类的对象,无法确定运行时的信息。

7. 任何需要依靠对象的成员和成员函数都不能定义为静态类型

C++中的static关键字可以用于声明静态成员变量(或数据成员)和静态成员函数。它们与类相关联,而不是与类的对象关联,因此可以被所有类的对象共享。通过使用关键字`static`在类中声明静态数据成员,可以将数据成员与类的对象解耦。它们只有一个实例,并且可以在类的任何成员函数中修改,从而可以用来记录该类的所有对象的统一信息。

// 静态数据成员
#include <iostream>class player {
public:player() {++count;}// 通过使用关键字`static`在类中声明静态数据成员,可以将数据成员与类的对象解耦。// 它们只有一个实例,并且可以在类的任何成员函数中修改,从而可以用来记录该类的所有对象的统一信息。static int count;
private:int id;
};
// 类的静态成员变量需要在类外进行定义
int player::count = 0;int main()
{player p1, p2, p3;std::cout << "total players: " << player::count << std::endl;return 0;
}
// 静态成员函数
// 静态成员函数可以使用与静态数据成员相同的语法进行声明:将`static`关键字放在函数的声明之前。
// 与非静态成员函数相比,它们没有this指针,并且只能对静态数据成员进行操作。
#include <iostream>class car {
public:car() {++count;}static int getCount() {return count;}
private:static int count;
};int car::count = 0;int main()
{car c1, c2, c3;std::cout << "number of cars : " << car::getCount() << std::endl;return 0;
}
// 使用静态成员变量实现单例模式
#include <iostream>class Singleton {
public:// 静态成员函数`getInstance()`返回`Singleton`类的单例实例。// getInstance()成员函数是一个静态成员函数,它只能访问静态成员变量,因此可以在类内定义,也可以在类外定义。static Singleton &getInstance() {// instance成员变量是一个静态局部变量,局部静态变量在第一次调用时被初始化,并一直存在直到程序结束,因此不需要在类外进行定义。static Singleton instance;// 返回一个静态局部变量instance的引用,从而实现了全局唯一的实例。// 由于instance是静态局部变量,它只会被初始化一次,并一直存在直到程序结束,// 因此Singleton类的使用者可以多次调用getInstance()来获得同一个实例,并且该实例的生命周期与程序的生命周期相同。return instance;}void foo() {std::cout << "hello world!" << std::endl;}
private:// 类中声明了一个私有的无参构造函数,使得该类不能被直接实例化。Singleton() {}~Singleton() {}
};int main()
{Singleton &s1 = Singleton::getInstance();Singleton &s2 = Singleton::getInstance();std::cout << (&s1 == &s2) << std::endl; // true// 通过对`s1`和`s2`取地址后,对返回的指针进行解引用,并调用其中的`foo()`函数。// 在C++中,对指针进行解引用可以使用`*`或者`->`符号。// `*`符号用在对指针变量本身进行解引用时,而`->`符号则用在对指向对象的指针进行解引用时。// 因此,`(&s1)->foo()`和`s1.foo()`实际上是等价的。// 对`s1`和`s2`取地址后,返回的是指向`Singleton`对象的指针。// 因为`foo()`函数是`public`成员函数,可以通过对象的指针调用。// 因此,在这里可以对指向`Singleton`对象的指针进行解引用,并调用其中的`foo()`函数。(&s1)->foo();(&s2)->foo();// 打印`s1`和`s2`的指针地址,通过输出结果可以发现,// `s1`和`s2`的指针地址是相同的,这说明它们指向了同一个`Singleton`类的实例。std::cout << std::hex << &s1 << std::endl;std::cout << std::hex << &s2 << std::endl;return 0;
}
// static成员变量和static成员函数的生命周期和共享特性
// static成员变量和static成员函数都是属于类的,而不是属于类的任何一个对象。
// 其生命周期与程序的生命周期相同,即它们在程序中只会被创建一次,不管有多少个类的对象被创建,它们都只有一份。
// static成员变量是在程序运行时分配的内存空间,而不是在类的对象创建时分配的,因此它们可以在多个对象之间共享数据。
// static成员函数没有this指针,所以它们不能访问非静态成员变量或函数,只能访问静态成员。
// 与普通成员变量和函数的生命周期不同,普通成员变量和函数的生命周期与对象相关,即每个对象都有自己的成员变量和成员函数。
// 与类的生命周期不同,类只是一个抽象概念,没有实际的内存空间,因此类不存在生命周期的概念。
// 与对象的生命周期不同,对象是类的一个实例,有自己的内存空间,当对象被销毁时,它的成员变量和成员函数也随之销毁。#include <iostream>class Person {
public:Person(std::string name, int age) : name_(name), age_(age) {count_++;}static int count_;static void countPrint() {std::cout << "total number of person: " << count_ << std::endl;}private:std::string name_;int age_;
};// 定义并初始化静态成员变量
int Person::count_ = 0;int main()
{Person p1("Alice", 25);Person p2("Bob", 30);Person p3("Tom", 35);// 由于count_是静态成员变量,所有Person对象共享该变量,因此在每次创建新对象时递增count_可以统计所有已创建的对象数量。// 输出总共创建的Person对象的数量为3,即使我们创建了多个对象,它们都只是count_的共享者而不是它们自己的副本。Person::countPrint(); // 输出3return 0;
}
// static成员变量的申明定义和初始化
// 在C++中,类的静态成员变量必须在类外进行定义和初始化。
// 这是因为静态成员变量不是对象的成员,而是整个类所共享的成员,因此需要在类外进行定义和初始化,以便被所有对象所共享。
// 虽然C++中的静态成员变量可以在类外定义和初始化,但是在使用该成员变量时,仍需要在类内进行声明。
// 因此,即使在类外定义和初始化了静态成员变量,仍需要在类内声明该成员变量的类型和名称。
#include <iostream>class Person {
public:Person(std::string name, int age) : name_(name), age_(age) {}void infoPrint() const {std::cout << "person " << total_++ << " : name : " << name_ << ", age : " << age_ << std::endl;}// 声明静态成员变量static int total_;
private:std::string name_;int age_;
};// 定义并初始化静态成员变量
int Person::total_ = 0;int main()
{Person p1("Alice", 28);Person p2("tom", 22);p1.infoPrint();p2.infoPrint();return 0;
}
// c++类的static成员变量声明定义和初始化
// 在C++中,类的静态成员变量可以在类外进行初始化,也可以在类内进行初始化。
// 如果在类内进行初始化,则需要在声明时进行初始化,
// 值得注意的是,如果静态变量在类内进行初始化,则必须将其定义为const或constexpr类型
#include <iostream>class MyClass {
public:// constexptr静态常量// 这个静态常量是在类内部定义和初始化的,因为它是一个const类型的变量。// 通过将静态常量定义为constexpr类型,可以将其作为编译时常量使用。// 如果希望在类中定义静态非常量,还是应该在类外进行初始化。// 这里需要注意的是,静态成员的定义和初始化应该放在同一文件中,否则编译器会出现多个定义的错误。// 如果不用constexpr修饰将报错:error: ISO C++ forbids in-class initialization of non-const static member ‘MyClass::MAX_NUM’// 如果不进行初始化将报错:error: constexpr static data member ‘MAX_NUM’ must have an initializerstatic constexpr int MAX_NUM = 100; // 已在编译期确定的常量// `constexpr`是C++11引入的关键字,用来指定在编译期能够计算出结果的表达式。// 在编写程序时使用`constexpr`可以提高代码的效率和可读性,在编译器进行编译时就已经完成了一些运算,提高运算速度,// 并且编译器在进行代码检查时也会对`constexpr`表达式进行检查,帮助程序员排错。// 在C++11之前,常量只能由`#define`和`const`定义。// 使用`#define`定义的常量是一种预处理器宏,不检查变量类型,也不进行类型安全检查,// 而使用`const`定义的常量需要在运行期进行计算,并且不方便在数组、结构体、枚举等数据类型中使用。// C++标准规定,constexpr函数应该满足以下要求:// 1. 必须有且只有一个return语句;// 2. 函数中不能有任何形式的循环;// 3. 函数中不能使用任何C++运行时库函数。static int factorial(int n) {if (n <= 1){return 1;} else {return n * factorial(n-1);}}static void print() {static constexpr int num = 5;int arr[MyClass::factorial(num)];std::cout << "the size of the array is " << sizeof(arr) / sizeof(int) << std::endl;}
};// 非静态成员变量不能再类外进行定义和初始化
// 否则报错:error: ‘int MyClass::num’ is not a static data member of ‘class MyClass’
// int MyClass::num = 0;// 不允许在定义(而不是声明)一个静态数据成员时使用`static`关键字。
// 否则报错:error: ‘static’ may not be used when defining (as opposed to declaring) a static data member [-fpermissive]
// 所以类的static成员变量只能再类里边声明,不能再类外边声明
// static int MyClass::num = 0;int main()
{std::cout << MyClass::MAX_NUM << std::endl;MyClass::print();return 0;
}

// 类的静态成员不占用类的内存空间
#include <iostream>class MyClass0 {
public:MyClass0() {}~MyClass0() {}};class MyClass1 {
public:MyClass1() {}~MyClass1() {}public:static std::string name;static int num;
};
std::string MyClass1::name = "Tom";
int MyClass1::num = 0;class MyClass2 {
public:MyClass2() {}~MyClass2() {}public:std::string name;int num;
};int main()
{std::cout << sizeof(MyClass0) << std::endl;MyClass0 obj0;std::cout << sizeof(obj0) << std::endl;std::cout << sizeof(MyClass1) << std::endl;MyClass1 obj1;std::cout << sizeof(obj1) << std::endl;std::cout << sizeof(MyClass2) << std::endl;MyClass2 obj2;std::cout << sizeof(obj2) << std::endl;return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/621681.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2624. 蜗牛排序

说在前面 &#x1f388;不知道大家对于算法的学习是一个怎样的心态呢&#xff1f;为了面试还是因为兴趣&#xff1f;不管是出于什么原因&#xff0c;算法学习需要持续保持。 题目描述 请你编写一段代码为所有数组实现 snail(rowsCount&#xff0c;colsCount) 方法&#xff0c;…

5.Pytorch模型单机多GPU训练原理与实现

文章目录 Pytorch的单机多GPU训练1)多GPU训练介绍2)pytorch中使用单机多GPU训练DistributedDataParallel(DDP)相关变量及含义a)初始化b)数据准备c)模型准备d)清理e)运行 3)使用DistributedDataParallel训练模型的一个简单实例 欢迎访问个人网络日志&#x1f339;&#x1f339;知…

数学建模day15-时间序列分析

时间序列也称动态序列&#xff0c;是指将某种现象的指标数值按照时间顺序排列而成的数值序列。时间序列分析大致可分成三大部分&#xff0c;分别是描述过去、分析规律和预测未来&#xff0c;本讲将主要介绍时间序列分析中常用的三种模型&#xff1a;季节分解、指数平滑方法和AR…

【Java-随笔】常用依赖

Jsoup https://mvnrepository.com/artifact/org.jsoup/jsoup <!-- "Jsoup"依赖项 --> <dependency><groupId>org.jsoup</groupId><artifactId>jsoup</artifactId><version>1.15.3</version> </dependency>H…

Mysql运算符

文章目录 比较运算符< > !IS NULL \ IS NOT NULL \ ISNULLLEAST() \ GREATEST() 查询数据大小&#xff08;字典序&#xff09;BETWEEN...AND...IN (SET) \ NOT IN (SET)LIKE 模糊查询REGEXP \ RLIKE 逻辑运算符逻辑运算符&#xff1a; OR &#xff08;||&#xff09;、A…

二分算法有关题目与解析

二分算法最重要的就是边界问题&#xff0c;边界一定要确定好&#xff0c;并且自己也要清晰&#xff0c;要不然就会混乱。 什么时候用到二分呢&#xff1f;当涉及到快速筛选有序序列的时候就应该想到&#xff0c;其实二分也经常跟排序算法结合着一起使用 关键模板 一个是确立…

SQL安全:常见手段

前面我们从基础的单表查询一直聊到优化&#xff0c;讲了SQL的很多内容。这一节我们来说说怎么让我们的数据库变得更安全。 为了实现常见的业务场景&#xff0c;数据库会提供很多的功能。有一些功能如果被攻击者利用&#xff0c;就很容易获取到不应该让其获取到的信息。比如uni…

演示kotlin的structured concurrency简化并发异步操作

文章目录 准备http客户端同步调用异步调用structured concurrency用例与机制浅析补充说明 用springboot的 kotlin demo&#xff0c;帮助理解structured concurrency简化异步并发调用的机制 准备http客户端 使用同时支持同步和异步调用的java.net.http.HttpClient Configurat…

vue笔记之$listeners

含义 将事件从父组件传递到子组件 作用 可以实现孙组件的数据传递到爷组件中去 示例 爷组件 <template><div id"app">我是爷组件<h3>{{ fromSunData }}</h3><fu fromSun"fromSun"></fu></div> </templ…

python期末考试:python的基本使用

1. 以下关于Python语言技术特点的描述中&#xff0c;错误的是&#xff08; &#xff09;。 A. 对于需要更高执行速度的功能&#xff0c;例如数值计算和动画&#xff0c;Python语言可以调用C语言编写的底层代码 B. Python比大部分编程语言具有更高的软件开发产量和简洁性 C. …

WEB服务器-Tomcat

3. WEB服务器-Tomcat 3.1 简介 3.1.1 服务器概述 服务器硬件 指的也是计算机&#xff0c;只不过服务器要比我们日常使用的计算机大很多。 服务器&#xff0c;也称伺服器。是提供计算服务的设备。由于服务器需要响应服务请求&#xff0c;并进行处理&#xff0c;因此一般来说…

【AI】人工智能和水下机器视觉

目录 一、初识水下机器视觉 ——不同点 ——难点 二、AI如何助力水下机器视觉 三、应用场景 四、关键技术 水下机器视觉&#xff0c;非常复杂&#xff0c;今天来简单讨论一下。因为目标识别更难。 水下机器视觉是机器视觉技术在水下环境中的应用&#xff0c;它与普通机器…

基于Springboot的网上点餐系统(有报告)。Javaee项目,springboot项目。

演示视频&#xff1a; 基于Springboot的网上点餐系统&#xff08;有报告&#xff09;。Javaee项目&#xff0c;springboot项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层体系结构&am…

【2024】OAK智能深度相机校准教程

编辑&#xff1a;OAK中国 首发&#xff1a;oakchina.cn 喜欢的话&#xff0c;请多多&#x1f44d;⭐️✍ 内容可能会不定期更新&#xff0c;官网内容都是最新的&#xff0c;请查看首发地址链接。 ▌前言 Hello&#xff0c;大家好&#xff0c;这里是OAK中国&#xff0c;我是Ash…

ThinkPHP6 自定义Excel导出

一、说明 1.需要安装Spreadsheet&#xff0c;如未安装自行composer安装即可 2.定义导出表格的表头&#xff08;及键值&#xff09; 3.数据内容需要与定义的表头一致 二、核心代码 try {// 获取表格数据$list (new Activity())->select()->toArray();if (!empty($l…

机器人跟踪性能量化指标

衡量机械臂关节轨迹跟踪控制的性能可以通过以下几个方面来进行&#xff1a; 跟踪精度&#xff1a;这是衡量机械臂关节轨迹跟踪控制性能的最重要的指标。它反映了机械臂实际运动轨迹与期望运动轨迹之间的偏差。跟踪精度越高&#xff0c;说明机械臂的控制性能越好。运动范围&…

抖音小店怎么选品?分享如何培养选爆品的思维,每个人都要学会

选品定店铺生死。 一个店铺能不能出单&#xff0c;能不能赚钱&#xff0c;店铺的商品占主要部分&#xff0c;商品才是电商店铺最核心的内容&#xff0c;一个货真价实&#xff0c;物美价廉的产品才是店铺的核心竞争力&#xff0c;运营和找达人都是让产品卖的更多&#xff0c;更…

三、MySQL实例初始化、设置、服务启动关闭、环境变量配置、客户端登入(一篇足以从白走到黑)

目录 1、选择安装的电脑类型、设置端口号 2、选择mysql账号密码加密规则 3、设置root账户密码 4、设置mysql服务名和服务启动策略 5、执行设置&#xff08;初始化mysql实例&#xff09; 6、完成设置 7、MySQL数据库服务的启动和停止 方式一&#xff1a;图形化方式 方式…

AI智能剪辑,快速剪辑出需要的视频

AI智能剪辑技术&#xff0c;是一种基于人工智能的技术&#xff0c;它能够通过机器学习和深度学习算法&#xff0c;自动识别视频中的内容&#xff0c;并根据用户的需求和喜好&#xff0c;快速地剪辑出需要的视频。 所需工具 &#xff1a; 一个【媒体梦工厂】软件 视频素材 …

软件报错msvcp120.dll丢失怎么办?总共有6个msvcp120.dll丢失的解决方法分享

一、msvcp120.dll是什么文件&#xff1f; msvcp120.dll是Microsoft Visual C Redistributable Package的一部分&#xff0c;它是运行许多Windows应用程序所必需的动态链接库文件之一。它包含了许多C函数和类&#xff0c;用于支持各种应用程序的正常运行。因此&#xff0c;当ms…