1. 程式人生 > >類與物件3

類與物件3

注:這是一篇補充部落格。
一、建構函式補充;
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)
 {}
private:
 int _year;
 int _month;
 int _day;
};

初始化列表:以一個“:”開始,用“,”分隔開資料成員列表,每個成員變數後跟一個“()”用來放初始值或者表示式。
需要注意的是:
(1).還是和建構函式賦值一樣,因為他們都可以賦值多次,而初始化只能有一次,所以初始化列表也只能在建構函式中出現一次。
(2).必須使用初始化列表的幾種情況:
a.引用成員變數;
b.const成員變數;
c.類型別成員(該類沒有預設建構函式)。
(3).一般儘量使用初始化列表。
3.explicit關鍵字(重點)
建構函式不僅可以構造與初始化物件,對於單個引數的建構函式,還具有型別轉換的作用,而explicit關鍵字就是阻止這種型別轉換的。
用explicit關鍵字修飾建構函式,將會禁止單參建構函式的隱式轉換。
二、static成員
1。概念:
宣告為static的類成員稱為類的靜態成員,用static修飾的成員變數,稱之為靜態成員變數;用static修飾的成員函式,稱之為靜態成員函式。靜態的成員變數一定要在類外進行初始化。
2.特點:
(1)靜態成員為所有類物件共享,不屬於某個具體的例項;
(2)靜態成員變數必須在類外定義,定義時不加static關鍵字;
(3)類靜態成員即可用類名:靜態成員或者物件那個,靜態成員來訪問;
(4)靜態成員函式沒有隱藏的this指標,不能訪問任何非靜態成員;(任何非靜態成員都可以訪問靜態成員,但是靜態成員不可以訪問任何非靜態成員)
(5)靜態成員和類的普通成員一樣,也有public、protected\private3種訪問級別,也可以具有返回值,const修飾符等引數。
三、友元
友元分為友元函式和友元類。
1.友元函式:

class Date
{
public:
 Date(int year, int month, int day)
  : _year(year)
  ,_month(month)
  ,_day(day)
 {}
 ostream& operator << (ostream& _cout)
 {
  _cout << d._year << " " << d._month << " " << d._day << endl;
  return _cout;
 }
private:
 int _year;
 int _month;
 int _day;
};
int main()
{
 Date d(2018,11,17);
 d << cout;
 return 0;
}

在這段程式碼種就能體現出來,我們要過載operator << ,但是發現,cout的輸出流物件和隱含的this指標在搶佔第一個引數的位置,this指標預設是第一個引數也就是左操作數了。但是實際種cout需要第一個形參物件,才能正常使用。所以我們就要將operator<<過載成全域性函式,但是這樣的話又會導致類外沒辦法訪問成員。

class Date
{
 friend ostream& operator << (ostream& _cout, const Date& d);
public:
 Date(int year, int month, int day)
  : _year(year)
  ,_month(month)
  ,_day(day)
 {}
private:
 int _year;
 int _month;
 int _day;
};
ostream& operator << (ostream& _cout,const Date& d)
 {
  _cout << d._year << " " << d._month << " " << d._day << endl;
  return _cout;
 }
int main()
{
 Date d(2018,11,17);
 cout << d << endl;
 return 0;
}


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

注意:友元函式可訪問類的私有成員,但不是類的成員函式
友元函式不能用const修飾
友元函式可以在類定義的任何地方宣告,不受類訪問限定符限制
一個函式可以是多個類的友元函式
友元函式的呼叫與普通函式的呼叫和原理相同
2、友元類
友元類的所有成員函式都可以是另一個類的友元函式,都可以訪問另一個類中的非公有成員。
友元類關係時單向的,不具有交換性;
友元關係不能傳遞。

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 = 2018, int month = 11, int day = 17)
  : _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;
};

怎麼區分誰是誰的友元類:
可以象徵的認為你和你的酒肉朋友一樣,他可以肆無忌憚的讓你請他吃飯,而卻不會請你吃飯,他就相當於你的友元類。