C++--类与对象(下)--构造函数--static成员--C++初始化(new)--友元--内部类

构造函数:

1.构造函数体赋值

对于函数体的赋值,我们常见的都是在函数体内进行赋值.如下:

class Date{
	
public:
	Date(int year,int month,int day){
		_year=year;
		_month=month;		//这就是比较经典的赋值了
		_day=day;
	}
	
private:
	int _year;
	int _month;
	int _day;
};

虽然上面构造函数,调用之后已经有了一个初始值,但是并不能将其称之为初始化,只能为赋初值,不能为初始化,因为初始化只能初始化一次,而成员函数内部可以进行多次的赋值.

2.初始化列表

这是一个新的概念,初始化列表,是以冒号开始,用逗号进行分割,且每个成员变量后面跟一个括号中的初始值或表达式.

class Date{
public:

	Date(int year, int month, int day)
		//====初始化列表: 真正初始化的位置
		//在构造列表写完的时候初始化已经完成了
		
		:_year(year)
		, _month(month)
		, _day(day)
		//没有写这个初始化列表的时候就是一个随机值
	{
		//不是初始化
		//赋值的地方
		/*_year = year;
		_month = month;
		_day = day;*/
	}

private:
	int _year;
	int _month;
	int _day;
};

成员函数中,在大括号外面的才是真正初始化的地方!

全缺省默认构造

Time(int hour=1, int minute=5, int second=30)		//全缺省默认构造
		:_hour(hour)
		, _minute(minute)	//真正赋予初始化的地方
		, _second(second)
		
	{
		//内部不是初始化,只是对随机值的一个赋值
		cout << "Time()" << endl;
	}

特点:

1)每个成员变量在初始化列表中只能出现一次

2)类中包含以下成员,必须放在初始化列表中进行初始化:

----引用成员变量
----const成员变量
----自定义类型成员(该类没有默认构造函数)

3)尽量在初始化列表中进行初始化,对于自定义变量来说,一定要在初始化列表中进行初始化

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

例题:执行当前程序,看输出的是什么?

class A {
public:

	//A(int a)
	//	:_a1(_a2)		//这样写刚好将值进行链式的赋予,都为1
	//	, _a2(a)

	A(int a)
		:_a1(a)
		, _a2(_a1)	//逆序,进行初始化,从下往上
					//在未进行赋值的时候,所有的都是随机值
	{}

	void Print() {
		cout << _a1 << " " << _a2 << endl;
	}
private:
	int _a2;
	int _a1;
};

void test4() {
	A aa(1);
	aa.Print();
}

具体理解:
在这里插入图片描述

3.explicit关键字

加入explicit可以禁止 单参构造隐式类型转换,单参构造隐试类型转换可就是,就是对于单个参数对其进行赋值的话会直接报错,需要分布进行.

class A{

public:
	explicit A(int a);	//====加入explicit可以禁止 单参构造隐式类型转换

	A(int a)
		:_a(a)
	{
		cout << "A(int)" << endl;
	}

private:
	int _a;
};

void test(){
	
	A aobj(10);		//简单构造
	A aobj2 = aobj;	//拷贝构造

	A aobj3 = A(20);	
	//===============================================================
	A aobj4 = 40;		//先创建匿名对象,然后调用赋值运算符,将匿名
					//对象的内容赋予aobj3
					//单参构造隐式类型转换
					//如果定义了explicit时这里就会报错!!!!!
}

static成员:

1.概念

在static修饰成员变量的时候,成为类的静态成员.利用static修饰成员函数,称之为静态成员函数,静态的成员变量一定要在类外进行初始化.

class A{
public:
	A(){
		
		++_count;
	}
	A(const A& a){
		
		++_count;
	}

	//this指针:指向当前调用此函数的对象
	//====static成员函数不包含this指针
	//因为static函数可以通过类名访问,没有对象,this没有指向
	static int getCount(){
		
		//缺少this指针,不能调用非static成员函数
		//fun();
		return _count;
	}
	//普通的成员函数包含this 指针
	void fun(){
		
		//可以调用static成员函数
		this->getCount();
		cout << "fun()" << endl;
	}

//private:
	//static成员属于所有对象
	//static成员变量: 必须在类外进行初始化
	static int _count;
};

2.特性

1.静态成员可以在所有的类中进行调用.

2.静态成员变量必须在类外进行定义

3.类的静态成员可以用 “::” 来对静态成员进行访问

int A::_count = 0;

4.静态成员函数没有隐藏函数this指针

5.静态成员和类的普通成员也是一样的,都有三种访问级别

C++初始化(new)

C++11支持非静态成员变量在声明时进行初始化赋值,这里不是初始化,就是给予一个缺省值而已.

class A{

public:

	A(int a=1)
		:_a(a)
	{}
private:

	//C++11新的初始化方式,在成员变量生命的时候,给一个缺省值
	//此处声明的缺省值,在没有其他值可选的时候,才会用
	//仅限于非static成员
	int _a=0;
	//int _a;		//随机值

	//static int _b = 10;		报错,静态的必须在类外进行初始化
};

友元:

1.友元函数

有元函数就是将一个成员函数定义成有元,让其可以访问私有类

class Date{

public:
	//有元函数的声明:此函数可以访问当前类的私有成员
	//不属于类的成员
	//可以放在类的任何地方,不影响使用
	friend void operator<<(ostream& _cout, const Date& d);	//当在这里进行friend声明以后,她就可以访问private所在内部的数据

	Date(int y = 1, int m = 2, int d = 3)
		:_y(y)
		, _m(m)
		, _d(d)
	{}

	//可访问私有成员
	void operator<<(ostream& _cout){
		
		_cout << _y << "-" << _m << "-" << _d << endl;		//访问后可以输出
	}

private:
	int _y;
	int _m;
	int _d;
};

1.友元函数可以访问私有类成员,但并不是类的成员函数

2.友元函数不能用const修饰

3.友元函数可以在任何部位进行声明,可以定义在类内部的任何地方

4.一个函数可以是多个类的友元函数

5.友元函数的调用和普通函数基本一致.

例题:日期类输入输出

对于友元函数来说,我们主要就是利用它来访问在类中的私有部分,将其内部的数据进行表示出来,但是对于日期类的输入和输出我们都是要把年月日进行依次输出,所以我们要在这里改变>>和<<两个符号的含义,让它可以执行对于日期类代码的正常的输入和输出,如下:

1.第一部分写一个类,并且进行有元定义,可以让外部函数对private内部进行访问

2.在外部定义出对应的函数

3.对其进行调用即可

class Date{

	//友元函数的声明
	friend ostream&  operator<<(ostream& _cout, const Date& d);
	friend istream& operator>>(istream& _cin, Date& d);
public:
	Date(int year, int month, int day)
		: _year(year)
		, _month(month)
		, _day(day)
	{

	}

private:
	int _year;
	int _month;
	int _day;
};


//返回值ostream可以支持连续的输出
ostream&  operator<<(ostream& _cout, const Date& d) {

	_cout << d._year << "-" << d._month << "-" << d._day;

	return _cout;
}
istream& operator>>(istream& _cin, Date& d){

	_cin >> d._year >> d._month >> d._day;
	return _cin;
}
//==输出
void test(){


	Date d(2021, 3, 7);
	//简写形式
	cout << d << endl;
	//完整形式
	//operator<<(cout, d);
	连续输出
	//cout << d << endl;
	//operator<<(cout, d)<<endl;
	cin >> d;		//输入操作,首先你先要将其定义出来

	cout << d << endl << d << endl << d << endl;;
}

这就是有元的具体作用

2.友元类

就是将一个类定义成有元,可以对其内部的类内部的private进行调用.
通过两个类的连接就可以利用Date对Time中的Private进行调用

class Date; 
class Time
{
	friend class Date; 		//有元声明

public:
	Time(int hour, int minute, int second)
		: _hour(hour)
		, _minute(minute)
		, _second(second)
	{}

private:
	int _hour;
	int _minute;
	int _second;
};


class Date
{
public:
	Date(int year = 1900, int month = 1, int day = 1)		//缺省默认构造
		: _year(year)
		, _month(month)
		, _day(day)
	{}

	void SetTimeOfDate(int hour, int minute, int second)
	{
		
		_t._hour = hour;
		_t._minute = minute;
		_t.second = second;
	}

private:
		int _year; 
		int _month;
		int _day;
		Time _t;
};

具体调用我就不详细写了,大家自己多看看,自己写.

内部类

内部类就是在一个类中,紧接着定义出另外一个类

1.内部类就是外部类的友元类

2.内部类可以定义在外部类的public、protected、private都可以

3.注意内部类可以直接访问外部类中的static、枚举成员,不需要外部类的对象/类名

4.sizeof(外部类)=外部类,和内部类没有关系

class A{
	
	public:
	//有元类的声明
	friend class C;
	//==内部类
	//==============================
	class B{
	public:
		void setA(A& a){
			a._a = _b;
		}
	private:
		int _b = 2;
	};
	//===============================

private:
	int _a = 1;
	static int _sa;		//定义静态成员变量
};

//有元类
class C{

public:
	void setA(A& a){		//在有元后对A中的进行调用
	
		a._a = _c;

		a._sa = 20;
		A::_sa = 5;
	}

private:
	int _c = 3;
};

int A::_sa = 10;	//对A中的静态变量进行赋值

你要明白A的类和A的内部类没有从属关系,只是放在一起而已,内部并不是包含关系的!
举例:
判断内部的字节大小,你可以直接运行,从而证明两者没有从属关系.

void test(){
	//判断是否从属
	int a = sizeof(A);

	int b = sizeof(A::B);

	cout << a <<"--"<< b << endl;
}

内容又点多,可能我在解释的方面还比够完善,当我有了更加深入的理解以后会补充,大家一起加油!!!多敲代码!!!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值