06-类和对象(中)

1.默认成员函数:

                                        初始化和清理:构造函数主要完成初始化工作

                                                                 析构主要完成清理工作

6个默认成员函数                   拷贝复制 :拷贝构造是使用同类对象初始化创建对象

                                                                 赋值重载主要是把一个对象赋值给另一个对象

                                                                 编译器生成的默认构造和opearator=引出浅拷贝问                                                                   题      

                                           取地址重载:主要是普通对象,const对象取地址,这两者很少

 2.const成员变量:

1.对象调用const成员函数:const 只能传给const
class Date
{
public:
	Date(int year, int mouth, int day)
	{
		_year = year;
		_mouth = mouth;
		_day = day;

	}
	//void Print()=>void Print(Date*this)
	void Print()const//=>void Print (const Date*this)
	{
		cout << _year << "-" << _mouth << "-" << _day << endl;
		//不能修改成员变量了,因为const修饰保护了*this
		//_year=10;
	}
	//p1和p2没区别,一般情况下喜欢p1的写法
	//const Date*p1;->*p1 指向的对象
	//Date const*p2;->*p2 指向的对象
	//Date*const p3;->p3  指针本身
private:
	int _year;
	int _mouth;
	int _day;

};
void f(const Date& d)
{
	d.Print();//const只能传给const 
}
int main()
{
	Date d1(2020, 4, 9);

	f(d1);
	d1.Print();//权限缩小

	return 0;
}

1.const对象不可以调用非const成员函数

2.非const对象可以调用const成员函数

3.const成员函数内不可以调用其他非const成员函数

4.非const成员函数内可以调用其它的const函数

 2.成员函数调用const成员函数:
class Date
{
public:
	Date(int year=0, int mouth=1, int day=1)
	{
		_year = year;
		_mouth = mouth;
		_day = day;

	}
	//void Print()=>void Print(Date*this)
	void Print()const//=>void Print (const Date*this)
	{
		cout << _year << "-" << _mouth << "-" << _day << endl;

	}
	void f1()//void f1(Date*this)
	{
		f2();//this->f2(this);//可以,属于权限缩小
	}
	void f2()const//void f2(const Date*this)
	{

	}
	/*void f3()//void f3(Date*this)
	{

	}
	void f4()const//void f4(const Date*this)
	{
		f3();//this->f(this);//不行,属于权限放大
	}*/
private:
	int _year;
	int _mouth;
	int _day;

};

int main()
{
	Date d1(2020, 4, 9);

	return 0;
}
 3.成员函数调用const成员函数:
class Date
{
public:
	Date(int year = 0, int mouth = 1, int day = 1)
	{
		_year = year;
		_mouth = mouth;
		_day = day;

	}
	//void Print()=>void Print(Date*this)
	void Print()const//=>void Print (const Date*this)
	{
		cout << _year << "-" << _mouth << "-" << _day << endl;

	}
	Date* operator&()
	{
		cout << "operator&()" << endl;
		return this;
	}
	 const Date* operator&()const//const Date*
	{
		cout << "operator&()const" << endl;
		return this;//const Date*
	}

private:
	int _year;
	int _mouth;
	int _day;
};

//取地址符重载
int main()
{
	Date d1;
	Date d2;
	const Date d3;

	cout << &d1 << endl;
	cout << &d2 << endl;
	cout << &d3 << endl;

	return 0;
}
4.外部函数调用operator: 
#include"Date.h"
void Fun(const Date& d3, const Date& d4)
{
	cout << d3 - d4 << endl;//d3.operator-(&d3,d4)//&d3的类型是const Date*
}
int main()
{
	Date d1(2019, 4, 18);
	Date d2(2020, 4, 18);
	cout << d1 - d2 << endl;//d1.operator-(&d1,d2)
	Fun(d1, d2);
	return 0;
}

 3.再识构造函数:(另一种构造函数,增加了初始化列表)

1.初始化列表式的构造函数:
//再识构造函数
class Date
{
public:
	Date(int year=0, int mouth=1, int day=1)
	{
	 //函数体内赋值
		_year = year;
		_mouth = mouth;
		_day = day;
	}

	//初始化列表式构造函数
	Date(int year = 0, int mouth = 1, int day = 1)
		:_year(year)
		, _mouth(mouth)
		, _day(day)
	{ //初始化列表

	}
private:
	int _year;
	int _mouth;
	int _day;

};
 2.为什么会有初始化列表这个东西?

必须用初始化列表形式构造函数的原因:

1.const成员变量

2.引用成员变量

3.没有默认构造函数的自定义成员变量

class A
{
public:
	A(int a=0)
		:_a(a)
	{}
private:
	int _a;
};
class B
{
public:
	//可以理解成初始化列表是对象的成员变量的定义的地方
	B(int b, int ref)
		:_aobj(b)
		,_ref(ref)
		, _n(5)
	{
		_x = 10;
	}
private:
	A _aobj;//没有默认构造函数(不要传参就可以调用的那个函数)
	int& _ref;//引用
	const int _n;//const
	//成员变量的声明
	int _x;
};

class Time
{
public:
	Time (int hour = 0)
		:_hour(hour)
	{
		cout << "Time()" << endl;
	}

private:
	int _hour;

};
class Date
{
public:

	/*Date(int day)
	{
		Time t(1);
		_t = t;
	}*/

	Date(int day)
		:_t(1)
	{
	}
private:
	int _day;
	Time _t;
};
3.成员变量在类中声明的次序就是其在初始化列表中初始化顺序,与其在初始化列表中的先后顺序无关 
class A
{
public:
	A(int a)
		:_a1(a)
		,_a2(_a1)
	{}
	void Print()
	{
		cout << _a1 << _a2 << endl;
	}
private:
	int _a2;
	int _a1;
};
int main()
{
	A aa(1);
	aa.Print();//1,随机值
	return 0;
}

4.隐式类型转换:关键字explicit可以防止出现隐式类型的转换 
class Date
{
public:
	//explicit Date(int year = 0) explicit可以防止出现隐士类型的转换
	Date(int year = 0)
		:_year(year)
		
	{ 

	}
private:
	int _year;
	int _mouth;
	int _day;

};
//C++11
class Date
{
public:
	Date(int year,int mouth,int day)
		:_year(year)
		,_mouth(mouth)
		,_day(day)
		
	{ 
	}
private:
	int _year;
	int _mouth;
	int _day;

};
int main()
{
	Date d(1);
	Date d1(1);//构造
	Date d1(1, 2, 3);
	//C++11
	Date d2 = { 1,2,3 };//隐士类型的转换,C++11才支持这种构造
	Date d2 = 2;//隐士类型的转换  构造出tmp(2),在用tmp拷贝构造d2(tmp)+优化成直接构造
	const Date& d2 = 2;//引用就是中间初始产生的临时对象
	Date d3 = d1;//拷贝构造

	return 0;
}

 4.static成员:

 设计一个类,可以计算这个类总计产生了多少对象
1.第一种设计容易被篡改
int n = 0;
class A
{
public:
	A()
	{
		++n;
	}
	A(const A& a)
	{
		++n;
	}
};

A f1(A& a)
{
	return a;//会创建一个临时变量A tmp=a;拷贝构造
}
A f2(A& a)
{
	return a;//会创建一个临时变量A tmp = a; 拷贝构造
}
int main()
{
	A a1;
	A a2;

	f1(a1);
	f2(a2);
  int n=1;//n被篡改了
  cout<<n<<endl;
	return 0;
}
 2.第二种设计可以防止n被篡改:类私有成员变量里面声明n,类外面通过访问符定义n;
class A
{
public:
	A()
	{
		++n;
	}
	A(const A& a)
	{
		++n;
	}
	static int Get()//没有this指针,函数中不能访问非静态的成员
	{
		return n;
	}
private:
	static int n;//声明 不属于某个对象,而是属于类的所以对象,属于这个类
	//n不在对象中,n在静态区
};

int A::n = 0;//定义

A f1(A& a)
{
	return a;
}
A f2(A& a)
{
	return a;
}
int main()
{
	A a1;
	A a2;

	f1(a1);
	f2(a2);

	cout << a1.Get() << endl;
	cout << A::Get() << endl;
	return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值