類與對象4

構造函數體賦值

之前學習瞭解到,在創建對象的時候,編譯器會通過調用構造函數,給對象中的各個成員變量賦一個合適的初始值。

class d
{
pubilc:
	d(int a,int b,int c)
	{
		_a = a;
		_b = b;
		_c = c;
	}
private:
	int _a;
	int _b;
	int _c;
};

雖然上述構造函數調用之後,對象中已經有了一個初始值,但是不能將其稱作爲類對象成員的初始化,構造函數體中的語句只能將其稱作爲賦初值,而不能稱作初始化。因爲初始化只能初始化一次,而構造函數體內可以多次賦值。所以,我們引進了初始化列表
初始化列表
以一個冒號開始,接着是一個以逗號分隔的數據成員列表,每個"成員變量"後面跟一個放在括 號中的初始值或表達式比如:

class d
{
pubilc:
	d(int a,int b,int c)_a(a),
	_b(b),
	_c(c)
	{}
private:
	int _a;
	int _b;
	int _c;
};

注意:
1. 每個成員變量在初始化列表中只能出現一次(初始化只能初始化一次)
2. 類中包含以下成員,必須放在初始化列表位置進行初始化:
引用成員變量,const成員變量,自定義類型成員(該類沒有默認構造函數)

class A 
{ 
public:    
	A(int a)        
	:_a(a)    
	{} 
private:    
	int _a; 
};
class d
{
pubilc:
	d(int a,int b,int c)_aa(a),
	_b(b),
	_c(10)
	{}
private:
	A _aa;//自定義變量
	int& _b;//引用
	const int _c;//const
};

3. 儘量使用初始化列表初始化,因爲不管你是否使用初始化列表,對於自定義類型成員變量,一定會先使用初始化列表初始化。
4. 成員變量在類中聲明次序就是其在初始化列表中的初始化順序,與其在初始化列表中的先後次序無關
.

static成員

聲明爲static的類成員稱爲類的靜態成員,用static修飾的成員變量,稱之爲靜態成員變量;用static修飾的 成員函數,稱之爲靜態成員函數。靜態的成員變量一定要在類外進行初始化

	static int getCount()
	{
		//
		/*Display();
		cout << _year << endl;*/
		return cnt;
	}

1.靜態成員函數: 函數內部沒有this指針
2.靜態成員函數不能訪問非靜態成員函數/變量–>因爲非靜態成員需要this指針,但是靜態成員函數內部缺少this指針,所以不能訪問.
3.非靜態成員函數可以訪問靜態成員函數/變量

4. 靜態成員變量, 所有對象共享此成員變量, 可以看成類成員
靜態成員變量不能在聲明的時候給默認
靜態成員不在對象模型中,一般存放在數據段, 不能在初始化列表中初始化

class Date
{
public:
	Date(int year = 2020, int month = 12, int day = 25)
		:_year(year)
		, _month(month)
		, _day(day)

	{
		++cnt;
		cout << "Date(int,int,int)" << endl;
	}

	Date(const Date& d)
		:_year(d._year)
		, _month(d._month)
		, _day(d._month)
	{
		++cnt;
		cout << "Date(const Date&)" << endl;
	}

	//靜態成員函數: 函數內部沒有this指針
	static int getCount()
	{
		return cnt;
	}

	void Display()
	{
		cout << _year << "-" << _month << "-" << _day << endl;
		getCount();
		cout << cnt << endl;
	}
private:
	int _year = 1;
	int _month = 1;
	int _day = 1;
public:
	static int cnt;

};

靜態成員變量/靜態成員函數訪問方式:

  1. 對象訪問
	cout << d.getCount() << endl;
	cout << d2.getCount() << endl;
	cout << &d.cnt << endl;
	cout << &d2.cnt << endl;
  1. 類名 + 作用域限定符
	cout << &Date::cnt << endl;
	cout << Date::cnt << endl;
	cout << Date::getCount() << endl;

友元

友元分爲:友元函數和友元類
友元提供了一種突破封裝的方式,有時提供了便利。但是友元會增加耦合度,破壞了封裝,所以友元不宜多用。

友元函數可以直接訪問類的私有成員,它是定義在類外部的普通函數,不屬於任何類,但需要在類的內部聲 明,聲明時需要加friend關鍵字。

class Date
{
public:
	//友元函數
	friend ostream& operator<<(ostream& outputS, Date& d);
	friend istream& operator >> (istream& inputS, Date& d);
Date(int year = 2020, int month = 12, int day = 25)
		:_year(year)
		, _month(month)
		, _day(day)
	{}

	Date(const Date& d)
		:_year(d._year)
		, _month(d._month)
		, _day(d._month)
	{}
private:
	int _year = 1;
	int _month = 1;
	int _day = 1;
};
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;    
	_cin>>d._month;    
	_cin>>d._day;       
	 return _cin; 
 }

說明:
1. 友元函數儘量少用,它是一種突破封裝的語法
2. 友元函數: friend + 正常函數的定義/聲明
3. 友元函數可以訪問類的私有成員
4. 友元函數不是類的成員函數,它是普通的非成員函數
5. 只需要在類中聲明友元函數,不需要在類中定義

class Date
{
public:
	friend ostream& operator<<(ostream& outputS, Date& d);
	friend istream& operator >> (istream& inputS, Date& d);
	friend class B;//定義B爲Date的友元類
	Date(int year = 2020, int month = 12, int day = 25)
		:_year(year)
		, _month(month)
		, _day(day)

	{}
private:
	int _year;
	int _month;
	int _day;
};
class B
{
public:
	//disPlay, fun, fun1都爲Date類的的友元函數
	void disPlay(const Date& d)
	{
		cout << d._year << d._month << d._day << endl;
	}

	void fun(const Date& d)
	{
		cout << d._year << d._month << d._day << endl;
	}

	void fun1(const Date& d)
	{
		cout << d._year << d._month << d._day << endl;
	}
};

說明:

  1. 如果一個類是另一個類的友元類,則此類中的所有成員函數即爲另一個類的友元函數
  2. 友元關係不能傳遞
  3. 友元類的所有成員函數都可以訪問另一個類中的非公有成員。

內部類

概念:如果一個類定義在另一個類的內部,這個內部類就叫做內部類。注意此時這個內部類是一個獨立的 類,它不屬於外部類,更不能通過外部類的對象去調用內部類。外部類對內部類沒有任何優越的訪問權限。
注意:內部類就是外部類的友元類。注意友元類的定義,內部類可以通過外部類的對象參數來訪問外部類中 的所有成員。但是外部類不是內部類的友元。
特性:
1.內部類可以定義在外部類的public、protected、private都是可以的。
2.注意內部類可以直接訪問外部類中的static、枚舉成員,不需要外部類的對象/類名。
3.sizeof(外部類)=外部類,和內部類沒有任何關係。

class A 
{ 
private:    
	static int k;    
	int h; 
public:    
	class B    
		{    
		public:        
			void foo(const A& a)        
			{            、
				cout << k << endl;//OK            
				cout << a.h << endl;//OK        
			}    
		}; 
};
 
int A::k = 1;
 
int main() 
{    
	A::B b;    
	b.foo(A());        
	return 0; 
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章