c++初始化列表和静态成员


一、初始化列表

类对于成员变量的赋值有两种方式

  • 函数体内赋值
  • 初始化列表
    函数体内赋值就是直接在构造函数中赋值即可,而初始化列表它是较为特殊的一种方式!
    初始化列表是在构造函数()之后以:开始,然后后面跟要初始化的变量,之后再跟(),括号里面的值或者表达式就是对这个变量的初始化!然后再以,作为分割,之后可以再跟成员变量赋值或者不跟,没有就不用再用逗号分割!
    如下:
    在这里插入图片描述
    为什么要出来初始化列表?函数体内赋值不好吗?

因为有些情况只有初始化列表才能完成!
如:引用、const修饰的、自定义类型(没有默认构造函数)

引用和const都是必须在定义的时候初始化赋值!
在这里插入图片描述
而const 修饰的不在定义的时候初始化,那么就改不了它了,他就是一个随机值了!
而类对象成员变量它的定义不是在类中,类里面仅仅只是对其声明,真正定义是在对象定义之后,对象调用它的构造函数在其初始化列表对其定义,而这些并不是在构造函数函数体内定义,函数厅内赋值仅仅只是对其再次赋值而已!如:成员变量中有自定义类型时,都说它会去自动调用这个自定义类型的构造函数,但是这是建立在它的构造函数是默认构造的前提下,如果不是就不行了!自定义类型成员它的调用是在初始化列表完成的!
成员是引用、const修饰,自定义类型

class stack
{
    
    
public:
	stack(int capacity)
	{
    
    
		_a = (int*)malloc(sizeof(int) * capacity);
		if (_a == nullptr)
		{
    
    
			perror("malloc fail\n");
			exit(-1);
		}

		_top = 0;
		_capacity = capacity;
	}

private:
	int* _a;
	int _top;
	int _capacity;
};

class B
{
    
    
public:
	B(int& a,int b = 2)
		:_a(a)
		,_b(b)
		,_st(10)
	{
    
    
	}

private:
	int& _a;
	const int _b;
	stack _st;

};

在这里插入图片描述
并且不能将其写在函数体内,只能写在初始化列表!
在这里插入图片描述
类成员变量的定义是在初始化列表定义的,他只是在类里面声明而已,所有这三类只能写在初始化列表!
而当不在初始化列表显示写出时,其实它也是定义好了的!我没在函数体内给它赋值,那么就是每给它赋值,它的值就是随机值!
在这里插入图片描述
当初始化列表没有写出时,其实它们还是照样要走初始化列表完成定义!
既然初始化这么神奇,那么为什么不一开始直接用初始化列表?
因为初始化列表不能完成全部的工作,有些时候赋值完成之后还要检查,或者给空间赋值
初始化的!
如:

class BB
{
    
    
public:
	BB(int capacity=4)
		:_a((int*)malloc(sizeof(int)* capacity))
		,_top(0)
		,_capacity(capacity)
	{
    
    
		if (_a == nullptr)
		{
    
    
			perror("malloc fail\n");
			exit(-1);
		}

		memset(_a, 0, sizeof(int) * _capacity);
	}

private:
	int* _a;
	int _top;
	int _capacity;
};

这段代码它仅仅只是在初始化列表完成初始化还是不够的,还需要检查_a开的空间是否成功,这时在初始化列表中就无法完成,需要在函数体内完成!

还有就是动态开辟一个二维数组,只是初始化列表并不能完成,需要在函数体内完成!

class AA
{
    
    
public:
	AA(int row=10,int col = 5)
	{
    
    
		_a = (int**)malloc(sizeof(int*) * row);
		if (_a == nullptr)
		{
    
    
			perror("malloc fail\n");
			exit(-1);
		}
		for (int i = 0; i < row; i++)
		{
    
    
			_a[i] = (int*)malloc(sizeof(int) * col);
			if (_a[i] == nullptr)
			{
    
    
				perror("malloc fail\n");
				exit(-1);
			}
		}
	}

private:
	int** _a;
};

动态开辟一个二维数组,是先将行开辟出来,然后再每一行有多少列开辟出来这样在初始化列表是无法完成的!需要在函数体内完成!就这样说吧,初始化列表能完成95%的事情但是剩下的5%需要在函数体内完成!
初始化列表初始化顺序与声明应一致
初始化列表在初始化声明的成员变量时,是按照声明的顺序进行初始化的!所有在初始化列表中,建议初始化顺序与声明顺序一致!

class C
{
    
    
public:
	C(int a)
		:_a(a)
		,_b(_a)
	{
    
    }

	void Print()
	{
    
    
		cout << _a << " " << _b << endl;
	}

private:
	int _b;
	int  _a;
	
};

int main()
{
    
    
	C c(1);
	c.Print();
	return 0;
}

这段程序是没有保持一致的,它运行出来的结果如下:
在这里插入图片描述

二、静态(static)成员

先来看一个场景,场景需求是统计一个类创建了多少对象,其实创建了多少对象,在创建对象之后救护调用一次构造,所以可以定义一个全局变量cnt来统计,然后在构造函数中++,拷贝构造之中也要++,因为有时是以一个已经存在对象初始化另一个不存在的对象!
全局变量统计类创建了多少个对象

int cnt = 0;
class Count
{
    
    
public:
	Count()
	{
    
    
		cnt++;
	}

	~Count()
	{
    
    
		cnt--;
	}
	
};

Count c1;

void fun()
{
    
    
	Count c2;
	cout << __LINE__ << " " << cnt << endl;
	
}

int main()
{
    
    
	cout << __LINE__ << " "<<cnt << endl;

	Count c;
	cout << __LINE__ << " " << cnt << endl;
	fun();
	cout << __LINE__ << " " << cnt << endl;
	
	return 0;
}

在这里插入图片描述
其中的__LINE__是显示文件行
但是定义了这个全局变量,在任意位置都能修改它!这样不安全,为了不能修改它,将其封装到类中使其成为类成员变量!
但是它要与普通成员变量不同,将其弄成静态成员变量!在前面加static
那么普通成员变量与静态成员变量有什么区别?

普通成员变量:属于每一个类对象,存储在类对象中
静态成员变量:属于类,属于每一个类共享,存储在静态区!它不在初始化列表定义,因为它存储在静态区,将其定义在类外边!

但是这样它是私有成员变量,访问不了它,要访问它,可以将其弄成公有成员变量或者写一个公有函数获取它!这个成员函数也可以设置为静态成员函数!静态成员函数无this指针,它不能访问非静态成员变量或非静态成员函数!
静态成员统计类创建了多少个对象

class Count
{
    
    
public:
	Count()
	{
    
    
		cnt++;
	}

	~Count()
	{
    
    
		cnt--;
	}
	static int Getcnt()
	{
    
    
		return cnt;
	}
private:
	static int cnt;
};

int Count::cnt = 0;
Count c1;

void fun()
{
    
    
	Count c2;
	cout << __LINE__ <<" "<< Count::Getcnt() << endl;
}

int main()
{
    
    
	cout << __LINE__ << " " << Count::Getcnt() << endl;

	Count c;
	cout << __LINE__ << " " << Count::Getcnt() << endl;

	fun();
	cout << __LINE__ << " " << Count::Getcnt() << endl;
	return 0;
}

只是将其弄成了静态成员函数之后,在这个函数体内无法调用类中的非静态成员函数,并且不能访问类中非静态成员变量!因为没有this指针!但是非静态成员函数可以调用静态成员函数和访问静态成员变量!
凡是经由static 修饰定义的都是存储在静态区去了,它的定义也就在类之外定义了!

猜你喜欢

转载自blog.csdn.net/m0_67768006/article/details/131403089