类和对象——初始化列表

news2024/9/21 4:31:41

目录

初始化列表

注意

单/多参数传入

explicit关键字

匿名函数


先前,我们知道有构造函数——用于给各成员变量一个初始值。

但是仍然不能称为是初始化,因为初始化只能初始化一次,但是构造函数里可以多次赋值

初始化列表

以日期类Date为例,进行一个初始化列表

class Date
{
public:
//初始化列表—每个成员定义的地方
	Date(int year, int month, int day)
		:_year(year) //成员变量会被赋值为括号内相应的值
		, _month(month)
		, _day(day)
        ,_x(1)
    {
        //_day=day;//此处只能写在中括号里,中括号外必须要有' () '去定义    
    }  //中括号内实现其他代码
private:
	int _year;
	int _month;
	int _day;

    const int _x=10;//const修饰的变量必须要在定义的时候初始化-后续不能修改,总之在类里必须有个地方进行赋值初始化
};

注意

1.缺省值是赋予初始化列表的

2.若初始化列表没有显示给值,就用这个缺省值

3.如果显示给值了,就不用这个缺省值(会先赋值缺省值,如果在列表里重新定义,就会重新赋值)

4.成员变量在类中声明次序就是其在初始化列表中的初始化顺序,与其在初始化列表中的先后 次序无关

单/多参数传入

单参数直接用 ' () '或者用' = '进行拷贝构造,多参数不仅可用' () ' 还能用' {} '

//单参数
class A
{
public:
	A(int i)
	:_a(i)
	{
		cout << "a(int i)" << endl;
	}
private:
	int _a;
};
//多参数
class B
{
public:
	B(int b1, int b2)
		//explicit B(int b1, int b2)
		:_b1(b1)
		, _b2(b2)
	{
		cout << "B(int b1, int b2)" << endl;
	}
private:
	int _b1;
	int _b2;
};

int main()
{
    const A& ref = 2;
	B bb1 (1, 2);
	B bb2 = { 2,2 };
	const B& ref2 = { 3,3 };//相同空间用引用,需转换类型,加const修饰
    return 0;
}

explicit关键字

构造函数不仅可以构造与初始化对象,对于单个参数或者除第一个参数无默认值其余均有默认值 的构造函数,还具有类型转换的作用。

class A
{
public:
	//explicit A(int i)//在构造函数这里加上explicit,可以防止隐式转换——这样主函数的两个转换就不能使用了
	A(int i)
	:_a(i)
	{
		cout << "A(int i)" << endl;
	}
	A(const A& aa)
		:_a(aa._a)
	{
		cout << "A(const A& aa)" << endl;
	}
	~A()
	{
		cout << "Delete" << endl;
	}
private:
	int _a;
};

int main()
{
    A aa1(1);
    /单参数构造函数的隐式类型转换
	//用2调用A构造函数,先生成一个临时对象,再用这个对象去拷贝构造aa2
	//编译器会优化,优化用2直接构造
	A aa2 = 2;//结果是直接构造,而不是先对2进行了拷贝构造,再把这个对象赋值给aa2

    //2会进行隐式类型转换,过程中会生成临时对象,具有常性,所以需要const去修饰
	const A& ref = 2;//2转换,生成了一个临时对象具有常性,需要用const来修饰
    
    return 0;
}

用explicit修饰构造函数,将会禁止构造函数的隐式转换。

匿名函数

顾名思义,就没进行命名的对象——生命周期仅存在于定义的那一行

    A aa6(6);//有名——生命周期在当前局部域
	A (7);//匿名——生命周期只在这一行
	//运行后发现的确调用了一次析构,说明出了这一行就会销毁

    //先定义再传入数据,代码量多
	SeqList s;
	s.PushBack(aa6);

	//用匿名对象传,直接放入想要的数据
	s.PushBack(A(8));

除此之外,匿名函数还有其他用法

class Solution {
public:
	int Sum_Solution(int n) {
		// ...
		cout << n << endl;
		return n;
	}
private:
};

int main()
{
    Solution s1;
	s1.Sum_Solution(10);
	Solution().Sum_Solution(100);//这种方法无需定义一个对象,直接赋值,调用类里的函数。
	return 0;

}

Static成员

现在我们知道,一个类里边可以建立很多个对象,那我们是否可以统计出累积创建了多少个对象,并且执行到某一处正在使用的还有多少个对象

引入

可以用以下代码

//全局变量
int n=0;
int m=0;
class A
{
    A()
    {
        ++n;
        ++m;
    }
    A(const  A& t)
    {
        ++n;
        ++m;
    }
    ~A()
    {
        --m;
    }
    void Print()
    {
    cout<<m<<" "<<n<<endl;
    }
private:

}
int main()
{
	A aa1;
	A aa2;
	cout << n << " " << m << endl;//共有情况,非private

    A();
	cout << n << " " << m << endl;
	
	Func(aa1);
	cout << n << " " << m << endl;
    return 0;
}

结果:

 修正

但是如果将n和m放在全局变量的话,容易被修改,那怎么解决呢?——放入类里,仅需要改变private里的内容

class A
{
public:
    {
        //....
    }
//private:
	//静态成员变量属于所有A对象,属于所有类
	  /*int n=0 ;//创建
	  int m=0 ;//正在使用 */err,因为这样的话,每个对象都会有一个m和n,但我们仅需要一个全局的,所有对象共有的
        
        static int n;
        static int m;
        
}

int A::m=0;
int A::n=0;

访问形式

int main()
{
	A aa1;
	A aa2;
	cout << A::n << " " <<A:: m << endl;//共有情况,非private
	cout << aa1.n << " " << aa1.m << endl;
    return 0;
}

static定义的特点

1.static定义的变量处于静态区里,不参与类大小的计算

sizeof(A);//———— 1

因为不参与类大小的计算,所以内存可视为0,但是类的构建是需要内存的,所以最少会分配一个字节的空间

int main()
{
    A* ptr = nullptr;
	cout << ptr->n << " " << ptr->m << endl;//为什么行得通?
    return 0;
}

因为此处n和m存在于静态区,类似于成员函数的公共代码区,所以一样可以访问。

2.静态成员变量属于所有A对象,属于所有类

3.在类中由于用static定义了——所以属于全局,所以不能给缺省值

4.静态变量不能走初始化列表,不属于对象里,故不能给缺省值,是在静态区里的

5.限制了,不能在外边直接访问并且修改,除非得到m/n的别名,访问方式同其他类' :: '

' . '

static静态成员函数

因为n和m是属于所有A对象,属于所有类,所以需要调用一次类去打印

若用匿名函数

int main()
{
    A();//能否用匿名函数去打印?
    A();
    A::Print();
    return 0;
}

若用匿名函数,那么同样也会调用一次类,那么就会对数据造成误差。

此时就要用到静态成员函数

static void Print()
	{
		//x++; //不能访问非静态,因为没有this指针
		cout << m <<" "<< n << endl;
	}

静态成员函数特点

1.不具有this指针

2.不能访问非静态变量(仅能访问static定义的变量)

倘若想对m和n进行修改呢???——就需要静态引用返回——既不会额外改变m也不会直接改变m

static int& GetM()
	{
		return m;
	}
++A::GetM();

例题

现在我们知道了通过每次的构造函数,可以实行计数

 (求1+2+3+...+n_牛客题霸_牛客网)

我们需要建立两个类,一个类用于返回结果,另一个用来统计——怎么统计?——通过每次的构造实现n个有序数字的累加

class Sum
{
public:
    Sum()//构造函数,开创一次就进入一次
    {
        _ret+=_i;
        _i++;
    }
    static int GetRet()
    {
        return _ret;
    }


private:
    static int _ret;//用static修饰,这样可以保证所有对象共用这个_ret
    static int _i;
};

int Sum::_ret=0;
int Sum::_i=1;
class Solution
{
public:
    int Sum_solution(int n)
    {
        Sum a[n]
        return Sum::GetRet();
    }
};

友元函数

对于有private限定符的类,若是某个定义在类外的函数需要调用类内部的数据,那么就需要友元函数

以输出流/输入流为例

class Date
{
	//友元声明——这样可以在外部访问私密对象
	//friend void operator<<(ostream& out, const Date& d);
	friend ostream& operator<<(ostream& out, const Date& d);
	friend istream& operator>>(istream& in, Date& d);
public:
    {
        //..
    }
private:
    {}
}

内部类

特点/定义

1.一个类定义在另一个类的内部

2.内部类是一个独立的类,不受限制,且是外部类的友元

class C
{
public:
	class D
	{
	public:
		void FuncD()
		{
			;
		}
	private:
		int _d;
	};
private:
	int _c;
};

sizeof(C);//  ——4

读取类C大小为4——因为内部类D还是独立的,所以读取的还是C的大小。

3.内部类是外部类的友元,内部类可以读取外部类的变量

class C
{
public:
	class D
	{
	public:
		void FuncD()
		{
			C cc;
			cc._c = 1;//内部类D可以直接访问外部类C的私有成员变量
		}
	private:
		int _d;
	};
	void func()
	{
		D dd;
	}
private:
	int _c;
};

4.public不能去掉,这样的话D类就不属于C类的公共区域里,

int main()
{
    C::D dd1;//但是定义还是得用C类域内部的D类定义
	//若去掉public,那么D类不是公共的,就不能调用
	cc.func();//也不能调用,因为func是属于D类的,但是D类不公共
    return 0;
}

内部类实现循环

再次谈回上边的例题,这次可以通过内部类来实现循环

(求1+2+3+...+n_牛客题霸_牛客网 (nowcoder.com))

class Solution {
    class Sum
    {
        public:
            Sum()
            {
                _ret+=_i;
                _i++;
            }
    };
public:
 int Sum_Solution(int n) { 
       Sum a[n];
       return _ret;
    }
private:
   static int _ret;
   static int _i;
};

int Solution::_ret=0;
int Solution::_i=1;

同理,还是需要用到static静态成员,将每次的_ret和_i 进行保存在全局变量里

本质上还是用到了构造函数的访问进行累加

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

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

相关文章

【Golang】解决Go test执行单个测试文件提示未定义问题

目录 背景 根本原因 解决方法 解决 多级引用或多个引用包的情况 总结 资料获取方法 背景 很多人记录过怎么执行Go test单个文件或者单个函数&#xff0c;但是要么对执行单文件用例存在函数或变量引用的场景避而不谈&#xff0c;要么提示调用了其它文件中的模块会报错。其…

Coremail中睿天下|2023年第二季度企业邮箱安全态势观察

7月24日&#xff0c;Coremail邮件安全联合中睿天下发布《2023第二季度企业邮箱安全性研究报告》&#xff0c;对2023第二季度和2023上半年的企业邮箱的安全风险进行了分析。 一、垃圾邮件同比下降16.38% 根据Coremail邮件安全人工智能实验室&#xff08;以下简称AI实验室&#…

c++(强生成关键字+可变参数模板+emplace)[26]

强制生成 不生成 在C中&#xff0c;可以通过一些方式来控制编译器是否生成某些特殊成员函数&#xff08;如默认构造函数、拷贝构造函数、拷贝赋值运算符、析构函数等&#xff09;。 默认生成&#xff1a;如果你没有显式地定义这些特殊成员函数&#xff0c;编译器会自动生成它们…

GNSS技术知识你知道多少?这些你或许还未掌握

GNSS信号频段 GNSS频谱图展示了不同的GNSS信号及其星座、载波频率、调制方案&#xff0c;以及所有这些信号在同一L波段频段内如何相互关联&#xff0c;是GNSS专业人员的必备工具&#xff0c;包括设计和开发GNSS系统的工程师&#xff0c;以及测试GNSS系统的工程师。 GNSS术语 …

如何清理电脑缓存垃圾

1、手动清理电脑缓存 C:\Users\yangguang\AppData\Local\Temp 注&#xff1a;yangguang 是自己电脑对应的用户目录 2、清理完后&#xff0c;电脑流畅了许多。

C++继承(2)——赋值转换、隐藏特性以及作用域

目录 一.子类和父类对象的赋值转换 子类对象赋值父类对象的另外两种方式&#xff1a; 总结&#xff1a; 二.父类与子类的作用域 1. 在继承体系中基类和派生类都有独立的作用域。 例&#xff1a; 2.作用域练习 练习1&#xff1a; 解决方法: 一.子类和父类对象的赋值转换 …

Reinforcement Learning with Code 【Code 2. Tabular Sarsa】

Reinforcement Learning with Code 【Code 2. Tabular Sarsa】 This note records how the author begin to learn RL. Both theoretical understanding and code practice are presented. Many material are referenced such as ZhaoShiyu’s Mathematical Foundation of Rei…

【C# 6.0】云LIS平台源码

基于云计算的区域LIS平台为医疗机构改善患者服务质量提供了强有力的支持&#xff0c;“以患者为核心”这一理念得到了充分实现&#xff0c;可以解决各医院LIS建设水平参差不齐的现状&#xff0c;并完善各医院内LIS系统的功能&#xff0c;实现数据标准统一、功能完善、性能可靠&…

VR全景旅游,智慧文旅发展新趋势!

引言&#xff1a; VR全景旅游正在带领我们踏上一场全新的旅行体验。这种沉浸式的旅行方式&#xff0c;让我们可以足不出户&#xff0c;却又身临其境地感受世界各地的美景。 一&#xff0e;VR全景旅游是什么&#xff1f; VR全景旅游是一种借助虚拟现实技术&#xff0c;让用户…

go env 配置(环境变量)说明

前提&#xff1a;已经安装好 golang 可正确的运行下面这段命令&#xff0c;来查看 go 的配置&#xff1a; go env 输出示例&#xff1a; 以上是我本地(windows)环境下输出的配置信息(环境变量) 我们这次就针对每个配置信息进行一个说明&#xff0c;具体到每个字段是什么意思…

浅谈Vue3 computed计算属性

什么是computed 官方给出的解释&#xff1a;接受一个 getter 函数&#xff0c;返回一个只读的响应式 ref 对象。该 ref 通过 .value 暴露 getter 函数的返回值。它也可以接受一个带有 get 和 set 函数的对象来创建一个可写的 ref 对象 // 只读 function computed<T>(ge…

远程控制软件安全吗?一文看懂ToDesk、RayLink、TeamViewer、Splashtop相关安全机制

目录 一、前言 二、远程控制中的安全威胁 三、国内外远控软件安全机制 【ToDesk】 【RayLink】 【Teamviewer】 【Splashtop】 四、安全远控预防 一、前言 近期&#xff0c;远程控制话题再一次引起关注。 据相关新闻报道&#xff0c;不少不法分子利用远程控制软件实施网络诈骗&…

直播预告 | 开源运维工具使用现状以及可持续产品的思考

运维平台自上世纪90年代开始进入中国市场&#xff0c;曾形成以传统四大外企&#xff1a;IBM、BMC、CA、HP为代表的头部厂商&#xff0c;还有一众从网管起家的国内厂商。2010年前后&#xff0c;出现了以Zabbix、Nagios、Cacti为代表的开源工具&#xff0c;后来又陆续出现了Prome…

如何计算文本的困惑度perplexity(ppl)

前言 本文关注在Pytorch中如何计算困惑度&#xff08;ppl&#xff09;为什么能用模型 loss 代表 ppl 如何计算 当给定一个分词后的序列 X ( x 0 , x 1 , … , x t ) X (x_0, x_1, \dots,x_t) X(x0​,x1​,…,xt​), ppl 计算公式为&#xff1a; 其中 p θ ( x i ∣ x &l…

Ansible之playbook剧本编写

一、playbook的相关知识 1.playbook简介 playbook是 一个不同于使用Ansible命令行执行方式的模式&#xff0c;其功能更强大灵活。简单来说&#xff0c;playbook是一个非常简单的配置管理和多主机部署系统&#xff0c;不同于任何已经存在的模式&#xff0c;可作为一个适合部署复…

3.5千伏硅化碳(SiC)深埋式超结二极管

目录 相关知识研究了什么文章创新点研究方法文章的结论 相关知识 在科学和工程技术领域&#xff0c;SEM通常是扫描电子显微镜&#xff08;Scanning Electron Microscope&#xff09;的缩写。因此&#xff0c;在 “外延SEM横截面图” 中&#xff0c;SEM指的是扫描电子显微镜&am…

分享一些精选的开源框架与代码!

今天主要是收集并精选了一些自己所了解和学习过的优秀的嵌入式开源框架代码和项目&#xff0c;不太了解的就不推荐给大家了&#xff0c;因为开源的东西实在是太多了&#xff0c;鱼龙混杂&#xff0c;所以取其精华去其糟粕是迫在眉睫的大事~ 当然也不要总是沉浸在开源的东西之中…

手把手教你Pytest+Allure2.X定制报告详细教程,给自己的项目量身打造一套测试报告-02(非常详细)

简介 俗话说“人靠衣服马靠鞍”一个项目做的在好&#xff0c;没有一分的漂亮的测试报告有时候也是很难在客户那边验收的&#xff0c;今天就带你们解决这一难题。 前边一篇文章是分享如何搭建pytestAllure的环境&#xff0c;从而生成一份精美的、让人耳目一新的测试报告&#…

【Linux 网络】 HTTPS协议原理 对称加密 非对称加密 数字证书

HTTPS协议 HTTPS协议和HTTP协议的区别什么是“加密” 和“解密”加密和解密的小故事 为什么要进行加密&#xff1f;臭名昭著的“运营商劫持”事件 常见加密方式对称加密非对称加密 数据摘要数字签名 HTTPS工作过程探究方案 1 &#xff1a; 只使用对称加密方案2 &#xff1a; 只…

微信小程序交易体验分常见问题指引

小程序交易体验分是为保障小程序用户的交易体验&#xff0c;促进开发者向用户提供更好的服务&#xff0c;帮助开发者更好的评估自身服务水平的机制。平台将对开发者在其小程序的违规行为进行判定&#xff0c;根据违规行为的严重程度对该小程序扣减不同分值的交易体验分&#xf…