初始化列表

目录

必须在初始化列表初始化的条件:

explicit

多参数强制类型转换

 静态成员

​编辑

 对于静态成员变量需要在构造函数里初始化吗?

静态成员函数:

题目1:

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

要求类对象只能在栈上:


必须在初始化列表初始化的条件:

1:const修饰的成员变量(只有一次初始化的机会,发生在定义的时候,也就是初始化列表

2:引用:(要变成其他变量的别名,只有一次初始化的机会,发生在定义,也就是初始化列表。

3:自定义类型成员(且该类没有默认构造)

例如:

#include
using namespace std;
class A
{
public:
	A(int a)
	{
		_a = a;
	}
private:
	int _a;
};
class B
{
public:
	B()
	{

	}
private:
	int _b;
	A a;
};

初始化列表_第1张图片

我们不运行也会报错 :如果没有在初始化列表中写的话,对于自定义类型A会调用其默认构造,因为类A没有默认构造,所以报错。

初始化列表_第2张图片

 总结:

explicit

class Date
{
public:
	Date(int year)
		:_year(year)
	{}
	Date& operator=(const Date&d)
	{
		if (this != &d)
		{
			_year = d._year;
			_month = d._month;
			_day = d._day;
		}
		return *this;
	}
private:
	int _year;
	int _month;
	int _day;
};
int main()
{
	Date d1(2022);
	Date d2 = 2022;
	return 0;
}

初始化列表_第3张图片

隐式类型转换。

 初始化列表_第4张图片

类比这里:

把整型i传递给一个临时变量,该临时变量的类型是double,再把该临时变量赋值给d。 

 初始化列表_第5张图片

 初始化列表_第6张图片

这里也是同样,把2022强制类型转换为Date类型传递给临时变量,再把该临时变量传递给d5. 

初始化列表_第7张图片

初始化列表_第8张图片

这里无法优化:这里是引用,必须用2022先构造一个对象,再用该对象引用。

explicit Date(int year)
		:_year(year)
	{}

我们在构造函数前面加上了explicit,就不会发生这些隐式类型转换:

初始化列表_第9张图片

Date(int year,int month=1,int day=1)
		:_year(year)
		, _month(month)
		, _day(day)
	{}

 这种半缺省,只用传一个参数的也支持隐式类型转换。

初始化列表_第10张图片

全缺省的也可以。

多参数强制类型转换

class Date
{
public:
	 Date(int year,int month,int day)
		:_year(year)
		, _month(month)
		, _day(day)
	{}
	Date& operator=(const Date&d)
	{
		if (this != &d)
		{
			_year = d._year;
			_month = d._month;
			_day = d._day;
		}
		return *this;
	}
private:
	int _year;
	int _month;
	int _day;
};
int main()
{
	/*Date d1(2022);
	Date d2 = 2022;
	const Date&d5 = 2022;*/
	Date d1 = { 2022, 10, 12 };
	Date d2(2022, 10, 12); 
	return 0;
}

初始化列表_第11张图片

int main()
{
	/*Date d1(2022);
	Date d2 = 2022;
	const Date&d5 = 2022;*/
	Date d1 = { 2022, 10, 12 };
	Date d2(2022, 10, 12); 
	const Date&d3 = { 2022, 10, 13 };
	return 0;
}

 静态成员

class A
{
public:
	A(int a = 0)
		:_a(a)
	{
		;
	}
private:
	int _a;
};
int main()
{
	A aa1(1);
	A aa2 = 2;
	return 0;
}

我们想要计算一共创建了多少个A类的对象。

int N = 0;
class A
{
public:
	A(int a = 0)
		:_a(a)
	{
		+ +N;
	}
	A(const A&aa)
		:_a(aa._a)
	{
		++N;
	}
private:
	int _a;
};
int main()
{
	A aa1(1);
	A aa2 = 2;
	cout << N << endl;
	return 0;
}

只有构造和拷贝构造可以创建对象:

int N = 0;
class A
{
public:
	A(int a = 0)
		:_a(a)
	{
		++N;
	}
	A(const A&aa)
		:_a(aa._a)
	{
		++N;
	}
private:
	int _a;
};
int main()
{
	A aa1(1);
	A aa2 = 2;
	A aa3 = aa1;
	cout << N << endl;
	return 0;
}

int N = 0;
class A
{
public:
	A(int a = 0)
		:_a(a)
	{
		++N;
	}
	A(const A&aa)
		:_a(aa._a)
	{
		++N;
	}
private:
	int _a;
};
void f(A aa)
{

}
int main()
{
	A aa1(1);
	A aa2 = 2;
	A aa3 = aa1;
	cout << N << endl;
	f(aa1);
	cout << N << endl;
	return 0;
}

验证了传值传参就是拷贝构造。 

int N = 0;
class A
{
public:
	A(int a = 0)
		:_a(a)
	{
		++N;
	}
	A(const A&aa)
		:_a(aa._a)
	{
		++N;
	}
private:
	int _a;
};
void f(A aa)
{

}
A f1()
{
	A aa;
	return aa;
}
int main()
{
	A aa1(1);
	A aa2 = 2;
	A aa3 = aa1;
	cout << N << endl;
	f(aa1);
	cout << N << endl;
	f1();
	cout << N << endl;
	return 0;
}

传值返回也是一次拷贝构造。 

尽量避免使用全局变量:

全局变量在哪里都可以修改。

 类里的静态受到类域的限制。

#include
using namespace std;

class A
{
public:
	A(int a=1)
		:_a(a)
	{
		;
	}
private:
	int _a;
	static int N;
};
int main()
{
	A aa1(1);
	A aa2 = 2;
	A aa3 = aa1;
}

aa1和aa2中有静态成员变量N吗?

初始化列表_第12张图片

总结:静态成员变量不存在于类对象里,存在于静态区。 

 对于静态成员变量需要在构造函数里初始化吗?

答:不需要,因为静态成员变量是每一个对象都共享的,每一次构造都对静态成员都会对静态成员变量进行修改。

静态成员变量的定义:

在全局定义,需要加上类域。

 只能在类里面使用静态成员变量。

初始化列表_第13张图片

静态成员变量的生命周期是全局的,作用域受类域限制 

 当静态成员变量是公有的时候,也是可以在类外面访问的

#include
using namespace std;
int A::N = 0;
class A
{
public:
	A(int a=1)
		:_a(a)
	{
		N++;
	}
private:
	int _a;
public:
	static int N;
};
int main()
{
	A aa1(1);
	A aa2 = 2;
	A aa3 = aa1;
	cout << A::N << endl;
	cout << aa1.N << endl;
}

对于静态成员变量为私有的情况,设置一个成员函数取出静态成员变量。

int GetN()
	{
		return N;
	}

静态成员函数:

初始化列表_第14张图片

如果我们想得到静态成员变量,使用静态成员函数没有对象也可以调用。

 初始化列表_第15张图片

 静态成员函数只能访问静态成员(没有this指针)

题目1:

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

class Sum
{
    public:
    Sum()
    {
        _ret+=_add;
        _add++;
    }
    static int GetRet()
    {
        return _ret;
    }
    private:
    static int _ret;
    static int _add;
};
int Sum::_ret=0;
int Sum::_add=1;
class Solution {
public:
    int Sum_Solution(int n) {
        Sum A[n];
        return Sum::GetRet();
    }
};

要求类对象只能在栈上:

class A
{
public:
	A(int a =0)
		:_a(a)
	{
	}
private:
	int _a;
};

初始化列表_第16张图片

class A
{
public:
	A GetObj(int a = 0)
	{
		A aa(a);
		return aa;
	}
	private:
	A(int a =0)
		:_a(a)
	{
	}
private:
	int _a;
};
int main()
{
	A aa3 = GetObj();
	return 0;
}

我们要调用函数GetObj,就需要先创建对象,我们要创建对象,就得先调用函数,产生矛盾。

class A
{
public:
	static A GetObj(int a = 0)
	{
		A aa(a);
		return aa;
	}
	private:
	A(int a =0)
		:_a(a)
	{
	}
private:
	int _a;
};
int main()
{
	A aa3 = A::GetObj();
	return 0;
}

我们可以用静态函数,静态函数不需要对象也可以调用。

你可能感兴趣的:(c++,算法,开发语言)