【C++进阶】对象的使用

news/2024/10/30 9:32:47/

static成员

对于特定类型的全体对象而言,有时候可能需要访问一个全局的变量。比如说统计某种类型对象已创建的数量。如果我们用全局变量会破坏数据的封装,一般的用户代码都可以修改这个全局变量,这时我们可以用类的静态成员来解决这个问题。非static数据成员存在于类类型的每个对象中,static数据成员独立该类的任意对象存在,它是与类关联的对象,不与类对象关联。

static成员优点:
1.static成员的名字是在类的作用域中,因此可以避免与其他类成员或全局对象名字冲突;
2.可以实施封装,static成员是可以私有的,而全局对象不可以;
3.阅读程序容易看出static成员与某个类相关联,这种可见性可以清晰地反映程序员地意图。

static成员需要在类定义体外进行初始化与定义,整形static成员可以在类定义体中初始化,不需要在类定义体外进行定义。

使用static成员实现类的个数统计:
CountedObject.h:

#pragma once
class CountedObject
{
public:CountedObject();~CountedObject();static int GetCount();
private:static int count_;//静态成员的引用性说明
};

CountedObject.cpp:

#include "CountedObject.h"int CountedObject::count_ = 0;//静态成员的定义性说明CountedObject::CountedObject()
{++count_;
}CountedObject::~CountedObject()
{--count_;
}int CountedObject::GetCount()
{return count_;
}

main.cpp:

#include <iostream>
using namespace std;
#include"CountedObject.h"int main()
{cout << CountedObject::GetCount() << endl;CountedObject co1;cout << CountedObject::GetCount() << endl;CountedObject* co2 = new CountedObject;cout << CountedObject::GetCount() << endl;delete co2;cout << CountedObject::GetCount() << endl;return 0;
}

static成员函数

static成员函数没有this指针,非静态成员函数可以访问静态成员,静态成员函数不可以访问非静态成员。

#include <iostream>
using namespace std;class Date
{
public:Date(int year) :year_(year){}static bool IsLeapYear(int year){return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);}bool IsLeapYear(){return (year_ % 4 == 0 && year_ % 100 != 0) || (year_ % 400 == 0);}
private:int year_;
};
int main()
{Date d(2012);cout << d.IsLeapYear()<<endl;cout << Date::IsLeapYear(2010) << endl;//不需要新建一个对象return 0;
}

四种对象作用域与生存期

栈对象:隐含调用构造函数(程序中没有显示调用)
堆对象:隐含调用构造函数(程序中没有显示调用)
全局对象、静态全局对象:全局对象的构造先于main函数,已初始化的全局变量或静态全局对象存储于.data段中,未初始化的全局变量或静态全局对象存储于.bss段中。
静态局部对象:已初始化静态局部对象存储于.data段中,未初始化的静态局部对象存储于.bss段中。

#include <iostream>
using namespace std;class Test
{
public:Test(int n) :n_(n){cout << "Test" << n << "..." << endl;}~Test(){cout << "~Test" << n_ << "..." << endl;}
private:int n_;
};int n;//未初始化的全局变量,初始值为0,n存储于.bss段中(block started by symbol)
int n2 = 100;//已初始化的全局变量,初始值为100,n2存储于.data段中
Test g(100);
static Test s(200);int main()
{cout << "Entering main ..." << endl;Test t(10);//栈上创建的对象,在生存期结束的时候自动释放{Test t(20);}{Test* t3 = new Test(30);//堆对象,要显示释放 作用域与生存期不等同//delete t3;}{static int n3;//n3存储于.bss中(编译期初始化)static int n4 = 100;//n4存储于.data段中(编译期初始化)static Test t4(40);//t4对象运行期初始化,存储于.data段}cout << "Exiting main ..." << endl;return 0;
}

输出如下:

在这里插入图片描述

static用法总结

1.用于函数内部修饰变量,即函数内的静态变量这种变量的生存期长于该函数,使得函数具有一定的“状态”。使用静态变量的函数一般是不可重入的,也不是线程安全的,比如strtok(3)。

2.用在文件级别(函数体之外),修饰变量或函数,表示该变量或函数只在本文件可见,其他文件看不到也访问不到该变量或函数。专业的说法叫“具有internal linkage”(简言之:不暴露给别的translation unit) 。

3.用于修饰类的数据成员,即所谓“静态成员”。这种数据成员的生存期大于class的对象(实例linstance) 。静态数据成员是每个class有一份,普通数据成员是每个instance有一份。

4.用于修饰class的成员函数,即所谓“静态成员函数”。这种成员函数只能访问静态成员和其他静态程员函数,不能访问非静态成员和非静态成员函数。

static与单例模式

保证一个类只有一个实例,并提供一个全局访问点,禁止拷贝。
使用嵌套类实现单例模式:

#include <iostream>
using namespace std;class Singleton
{
public:static Singleton* GetInstance(){if (instance_ == NULL){instance_ = new Singleton;}return instance_;}//static void free()//{//    if (instance_ != NULL)//    {//        delete instance_;//    }//}class Garbo{public:~Garbo(){if (Singleton::instance_ != NULL){delete instance_;}}};
private:Singleton(const Singleton& other);//拷贝构造函数声明为私有 禁止拷贝Singleton& operator=(const Singleton& other);//=运算符声明为私有 禁止拷贝Singleton(){cout << "Singleton..." << endl;//只调用了一次说明只创建了一个对象}~Singleton(){cout << "~Singleton..." << endl;}static Singleton* instance_;static Garbo garbo_;//利用对象的确定性析构
};Singleton* Singleton::instance_;//定义性说明
Singleton::Garbo Singleton::garbo_;//定义性说明int main()
{//Singleton s1;//Singleton s2;Singleton* s1 = Singleton::GetInstance();Singleton* s2 = Singleton::GetInstance();//Singleton::free();return 0;
}

使用局部静态对象实现单例模式:

#include <iostream>
using namespace std;class Singleton
{
public:static Singleton& GetInstance(){static Singleton instance;//局部静态对象return instance;}private:Singleton(const Singleton& other);//拷贝构造函数声明为私有 禁止拷贝Singleton& operator=(const Singleton& other);//=运算符声明为私有 禁止拷贝Singleton(){cout << "Singleton..." << endl;//只调用了一次说明只创建了一个对象}~Singleton(){cout << "~Singleton..." << endl;}static Singleton* instance_;
};Singleton* Singleton::instance_;//定义性说明int main()
{//Singleton s1;//Singleton s2;Singleton& s1 = Singleton::GetInstance();Singleton& s2 = Singleton::GetInstance();//Singleton::free();return 0;
}

const成员函数

const成员函数不会修改对象的状态,const成员函数只能访问数据成员的值,而不能修改它。

const对象

如果把一个对象指定为const,就是告诉编译器不要修改它,const对象不能调用非const成员函数。

mutable

用mutable修饰的数据成员即使在const对象或const成员函数中都可以被修改。比如记录某个变量的输出次数,变量不变,但输出次数要加一,此时就可以用mutable修饰输出次数。

#include <iostream>
using namespace std;class Test
{
public:Test(int x) :x_(x),outputTimes_(0){}int GetX() const {cout << "const GetX ..." << endl;return x_;}int GetX()//可以构成重载{cout << "GetX ..." << endl;return x_;}void Output() const{cout << "x=" << x_ << endl;outputTimes_++;}int GexOutputTimes() const{return outputTimes_;}
private:int x_;mutable int outputTimes_;
};int main()
{const Test t(10);t.GetX();Test t2(20);t2.GetX();t.Output();t.Output();cout << t.GexOutputTimes() << endl;return 0;
}

http://www.ppmy.cn/news/33087.html

相关文章

Linux虚拟机磁盘扩容、Docker容器磁盘满的问题、Docker安装nginx

文章目录虚拟机扩容1、外部配置2、具体扩容步骤3、扩容后效果Docker容器磁盘满的情况意外情况使用docker安装nginx前言 在创建虚拟机的时候&#xff0c;分配的磁盘空间只有40个G。使用了一段时间后&#xff0c;系统提示磁盘空间满了。在使用Docker安装镜像的时候&#xff0c;由…

C语言实现单链表(超多配图,这下不得不学会单链表了)

目录 一&#xff1a;什么是链表&#xff1f; 二&#xff1a;创建源文件和头文件 (1)头文件 (2)源文件 三&#xff1a;实参和形参 四&#xff1a;一步步实现单向链表 &#xff08;1&#xff09;建立一个头指针并置空 &#xff08;2&#xff09;打印链表&#xff0c;便于…

技术掉:PDF显示,使用pdf.js

PDF 显示 场景&#xff1a; 其实直接显示 pdf 可以用 iframe 标签&#xff0c;但产品觉得浏览器自带的 pdf 预览太丑了&#xff0c;而且无法去除那些操作栏。 解决方案&#xff1a;使用 pdf.js 进行显示 第一步&#xff1a;引入 pdf.js 去官网下载稳定版的 pdf.js 文件 然后…

PaddleClas套件——PP-ShiTuV2模型详解

1. PP-ShiTuV2模型介绍 PP-ShiTuV2 是基于 PP-ShiTuV1 改进的一个实用轻量级通用图像识别系统&#xff0c;由主体检测、特征提取、向量检索三个模块构成&#xff0c;相比 PP-ShiTuV1 具有更高的识别精度、更强的泛化能力以及相近的推理速度*。主要针对训练数据集、特征提取两个…

蓝桥杯嵌入式第五课--输入捕获

前言输入捕获的考题十分明确&#xff0c;就是测量输入脉冲波形的占空比和频率&#xff0c;对我们的板子而言&#xff0c;就是检测板载的两个信号发生器产生的信号&#xff1a;具体来说就是使用PA15和PB4来做输入捕获。输入捕获原理简介输入捕获能够对输入信号的上升沿和下降沿进…

OpenAI 发布GPT-4——全网抢先体验

OpenAI 发布GPT-4 最近 OpenAI 犹如开挂一般&#xff0c;上周才刚刚推出GPT-3.5-Turbo API&#xff0c;今天凌晨再次祭出GPT-4这个目前最先进的多模态预训练大模型。与上一代GPT3.5相比&#xff0c;GPT-4最大的飞跃是增加了识图能力&#xff0c;并且回答准确性也得到显著提高。…

QT串口助手开发3串口开发

系列文章目录 QT串口助手开发3串口开发 QT串口助手开发3系列文章目录一、UI界面程序的编写二、发送框程序编写一、UI界面程序的编写 根据上文的未解决问题&#xff1a;我们打开串口按钮打开后只能选择关闭串口&#xff0c;所以这个是循环的过程 上文链接 所以按钮对应的槽函数…

机器学习中的归一化问题_梯度下降做归一化的必要性_数据缩放_最大最小值归一化方法---人工智能工作笔记0029

然后我们再来看,为什么说只要是用到了梯度下降法,那么必须要做归一化 首先我们来看,如果一个人下山,那么我们说,我们每次去求,最优解,也就是利用目标函数,带入theta值,然后求出对应的y值,也就是预测值,然后找到这个点以后,就可以求出斜率对吧,然后斜率,如果 为0的时候,那么就说…