【C++】类和对象——初始化列表和static修饰成员

首先我们来谈一下初始化列表,它其实是对于我们前边构造函数体内初始化的一种补充,换一种说法,它以后才是我们构造函数的主体部分。
我们先考虑一个问题,就是一个类里面有用引用const初始化的成员变量,比如说:
在这里插入图片描述
在构造函数中我们是不能给c和d进行赋值的,因为这两种类型只能在初始化时去赋值,在这种情况下,我们的初始化列表就有用处了
我首先写一下它的基本用法,就是语法所规定

A(int aa=1,int bb=2,int cc=3)
	:a(aa)//初始化列表初始化
	,b(bb)
	,c(cc)
	,d(0)
{
	//函数体内初始化
}

这其实就是一个构造函数,两个大括号之间的就是我们之前所见过的构造函数在函数体内初始化,而上面所加的就是这里要说的初始化列表初始化,并且它们是可以混着用
下面一个问题,我如果在初始化列表不显示写(比如a成员的初始化),那么它还会不会初始化a这个成员变量?
答案是,因为初始化列表会初始化所有成员变量,即使你不写。为什么呢?我们之前是不是说过如果一个内置类型不写构造函数,它会被默认初始化为随机值,而对于一个没写构造函数的自定义类型则会去调用它的默认构造函数,这个过程实际上就是在初始化列表完成的。还有一个现象,就是我们会给成员变量缺省值,如果没有给构造函数,就会按缺省值来,这个过程也是在初始化列表完成的
除了这引用和const修饰的成员变量,还有自定义类型无默认构造或者说就算有默认构造但是我不想用给的缺省值我想自己传,这种情况需要用初始化列表,

#include<iostream>
using namespace std;
class B {
public:
	B(int ret1) {
		_ret = ret1;
	}
private:
	int _ret;
};
class A {
public:
	A(int aa = 1, int bb = 2, int cc = 3)
		:a(aa)//初始化列表初始化
		, c(cc)
		, d(0)
		, r(0)
{
	//函数体内初始化
}
private:
	int a;
	char b;
	int& c;
	const int d;
	B r;
};
int main() {
	A a;
	return 0;
}

那么能不能取消掉函数体呢(就是构造函数里的大括号及里面的东西)?当然不能,函数体内可以做一些检查和初始化的工作,这是初始化列表做不了的,比如说:
在这里插入图片描述
最后要知道初始化列表初始化的顺序声明顺序
在这里插入图片描述
而不是初始化列表中写的顺序
在这里插入图片描述
下面一个例子可以证明一下
在这里插入图片描述
就是先用_b初始化_a,此时_b还是随机值,所以第一个打印随机值
请添加图片描述
下一个问题就是我们的static修饰成员,这里的成员包括成员变量和成员函数,我们先来看成员变量,
有这样一个问题,就是我们想看一下一个类创建了多少个对象,我们该怎么做呢?我们当然可以创建一个全局变量,每当调用构造函数或者拷贝构造时就让它++,这样是没问题的,但假如有多个类呢?并且这个全局变量也容易被更改。我们这时用static变量就显得很好了,下面先说一下它的声明和定义形式
在这里插入图片描述
==为什么要声明和定义分离呢?==难道不能像非静态成员变量一样给缺省值吗?当然不能,因为缺省值是在我们上面说的初始化列表时用的,静态成员变量是没有在初始化列表中
下面我们就可以写统计一共创建了多少个对象的代码了

class A {
public:
	A(int ret = 1) {
		_a = ret;
		count++;
	}
	A(const A& aa) {
		_a = aa._a;
		count++;

	}
	int getcount() {
		return count;
	}
private:
	int _a;
	static int count;//声明
};
int A::count = 0;//定义
A Func() {
	A a;
	return a;
}
int main() {
	A a;
	Func();
	cout << a.getcount() << endl;
	return 0;
}

我们这里成员变量是私有的,受访问限定符的限制,所以不能直接访问,我们可以给一个函数把count的值传出来getcount函数),并且这个函数还有一个好处就是我们无法修改count的值,我们要调用这个getcount函数的时候我们需要一个对象,那么假如没有对象呢?我们可以创建一个有名对象,也可以创建一个匿名对象,就像下面这样:
在这里插入图片描述
我们创建对象是为了统计之前A类构建了多少个对象,所以要减去对应的值,另外,匿名对象的生命周期只在这一行,过了这一行就会去调用它的析构函数,如果不想创建对象呢?
那么这时就可以用到我们的static修饰的成员函数了,下面是static修饰的成员函数,基本形式像下面这样
在这里插入图片描述

在这里插入图片描述
调用可以上面这两种方法调用,就不一定用对象去调用,如果不用static修饰,第一种调用是不行的,并且这种函数它是没有this指针的,就意味着在这个函数内是不能访问非静态成员变量

不管是变量还是函数,只要用static修饰,它们都像一个专属这个类的全局的变量或函数一样
并且static修饰的成员变量就可以看成专属于某个类的全局变量,用sizeof计算对象大小时也是不算static修饰的变量的大小的

  • 18
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值