C++:类和对象3

本文详细探讨了C++中构造函数的使用,特别是构造函数的初始化列表,强调了初始化与赋值的区别。文章指出,初始化列表用于类对象成员的初始化,而成员的初始化顺序遵循它们在类中的声明顺序。此外,文章提到了引用、const成员和无默认构造函数的类类型必须在初始化列表中初始化。还讨论了`explicit`关键字的作用,防止单参数构造函数的隐式转换。同时,文章阐述了编译器何时生成默认构造函数的情况,并解释了`static`成员的特性和用法,包括静态成员函数与普通成员函数的区别。最后,介绍了友元函数和友元类的概念,以及内部类的特性,强调了它们在访问控制和代码设计中的重要性。
摘要由CSDN通过智能技术生成
再谈构造函数
  • 初始化列表
    例如:
class Date
{
public:
	Date(int year, int month, int day)
 	{
		_year = year;
		_month = month;
		_day = day;
 	}
private:
	int _year;
	int _month;
	int _day;
};

虽然上面的构造函数调用之后,对象中已经有了一个初始值,但是不能将其称作为类对象成员的初始化,构造函数体中的语句只能将其称作为赋初值,而不能称作初始化。因为初始化只能初始化一次,而构造函数体内可以多次赋值。
若要初始化类对象成员,可采用以一个冒号开始,接着是一个以逗号分隔的数据成员列表,每个"成员变量"后面跟一个放在括号中的初始值或表达式,这种称为初始化列表,但是采用这种方式会产生一些问题,因为初始化列表中的成员出现次序,并不代表真正的初始化次序,成员变量的初始化次序是其在类中的声明次序,例如:

class Date
{
public:
	Date(int year=1900, int month=3, int day=3)
		: _year(year)
		//初始化,赋值不是初始化,因为初始化只能进行一次,而赋值可以进行多次
		, _month(_day)
		, _day(day)
	{}
private:
	int _year;
	int _month;
	int _day;
};
int main()
{
	Date d(2019, 3, 2);
	return 0;
}

它的结果是2019,随机值,2,因为他是按照类中成员的声明顺序来初始化的,在初始化_month时,由于_day还没有初始化,因此为随机值。因此最好不要使用成员去初始化成员,因为在一些情况下有的成员还没有初始化。
注意

  1. 每个成员变量在初始化列表中只能出现一次(初始化只能初始化一次)
  2. 类中包含以下成员,必须放在初始化列表位置进行初始化:
    引用成员变量,因为引用必须在定义时初始化,并且不能重新赋值
    常量成员,包括const成员变量,因为常量只能初始化,不能赋值
    没有默认构造函数的类类型,因为使用初始化列表可以不必调用默认构造函数来初始化,而是直接调用拷贝构造函数初始化,例如:
class Time
{
public:
	Time(int hour, int minute, int second)
	:_hour(hour)
	, _minute(minute)
	, _second(second)
	{
		cout << "Time(int,int,int)" << endl;
	}
private:
	int _hour;
	int _minute;
	int _second;
};
class Date
{
public:
	Date(int year)
	:_year(year)//const修饰的变量必须在初始化列表中初始化
	,_t(0,0,0)//没有默认构造函数的类类型必须在初始化列表处初始化
	, _day1(_day)//引用类型必须在初始化列表中初始化,因为引用在定义时必须初始化,而且引用不能重新赋值
//在初始化列表中,不能使用this指针,因为此时对象还没有构造好,this指针是指向对象的,因此不能使用
	{
		_month = 2;
		_day = 2;
	}
	void Display()
	{
		cout << this->_year << endl;
		cout << this->_month << endl;
		cout << this->_day << endl;
		cout << this->_day1 << endl;
	}

private:
	const int _year;
	int _month;
	int _day;
	int& _day1;
	Time _t;
};
void Test()
{
	Date d(2020);
	d.Display();
}
int main()
{
	Test();
	return 0;
}

构造了一个Time类,它没有默认构造函数,显式构造函数是非全缺省构造函数,当在Date类中定义一个Time类的对象_t时,必须在Date类的初始化列表中对_t进行初始化,且const修饰的_year必须在初始化列表中初始化,引用类型也必须在初始化列表中初始化。

3.在初始化列表中,不能使用this指针,因为this指针是指向对象的,当前初始化列表中对象还没有构造成功,因此不能使用。在构造函数体中可以使用,因为此时对象已经构造完成。
4.在编译器编译期间,已经为主函数分配了栈空间,主函数在运行期间所需要的栈的大小用ebp和esp两个寄存器标记,这个空间已经包含了函数体的局部对象,但其实在构造函数调用之前,对象是不存在的,也就是没有构造对象,但已经分配好了对象所需空间。

  • explicit关键字
    用explicit修饰构造函数,将会禁止单参构造函数的隐式转换,也就是explicit只能修饰单参构造函数,意思是表明该构造函数是显式的,与之对应的是implicit&#x
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值