C++-類與對象(3)

類與對象(3)

再學構造函數

構造函數體賦值

先構造一個帶有全缺省的日期類

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,int month,int day)
        :_year(year)
        ,_month(month)
        ,_day(day)
    {
        _year = year;
        _month = month;
        _day = day;
    }
  private:
    int _year;
    int _month;
    int _day;
};

初始化列表以:開始,接着用一個,分隔的數據成員列表,每個“成員變量”後面跟一個放在括號內的初始值或者表達式

注意事項:

1、每個成員變量在初始化列表中只出現一次(初始化只能初始化一次)

2、類中的成員:“引用成員變量”,“const成員變量”,“類類型成員(該類沒有默認構造函數)”

class skr
{
  public:
    skr(int a)
    :_a(a)
    {
        
    }
  private:
    int _a;
};

class cxk
{
  public:
  	cxk(int a,int ref)
    :_aobj(a)
    ,_ref(ref)
    ,_n(10)
    {
        
    }
  private:
    skr _aobj;
    int& _ref;
    const int _n;
}

3、儘可能使用初始化列表初始化,因爲不管你是否使用初始化列表,對於自定義類型成員變量,一定會先使用初始化列表初始化。

class Time
{
public:
 	Time(int hour = 0)
 	:_hour(222)
 	{
 		cout << "Time()" << endl;
 	}
private:
 	int _hour;
};
class Date
{
public:
 	Date(int day)
 	{}
private:
 	int _day;
 	Time _t;
};

int main()
{
 	Date d(1);
}

打印結果如圖

類1

4、成員變量初始化列表的順序按照在類中聲明成員變量的順序,與初始化列表的順序無關

class Array
{
public:
 Array(int size)
 :_size(10)
 , _array((int*)malloc(sizeof(int)*_size))
 {}
private:
 int* _array;
 int _size;
};
explicit關鍵字

用explicit修飾構造函數,將會禁止單個參數的構造函數的隱式轉換

static成員

聲明爲static的類成員稱爲類的靜態成員,用static修飾的成員變量,稱之爲靜態成員變量;

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

#include <iostream>
using  namespace std;
class A
{
public:
  A() {++_scount;}
  A(const A& t) {++_scount;}
  static int GetACount() {return _scount;}
private:                                  
  static int _scount;                     
};                   
                       
int A::_scount = 0;
                     
void TestA()       
{           
  cout<<A::GetACount()<<endl;
  A a1,a2;                   
  A a3(a1);                  
  cout<<A::GetACount()<<endl;
}                               
int main()
{         
  TestA();
  return 0;
} 

注意!!

注意!!

注意!!

靜態的成員變量一定要在類外進行初始化

static特性

1、靜態成員爲所有類對象所共享,不屬於某個具體的實例

2、靜態成員變量必須在類外定義,定義時不添加static關鍵字

3、類靜態成員即可用類名::靜態成員或者對象.靜態成員來訪問

4、靜態成員函數沒有隱藏的this指針,不能訪問任何非靜態成員

5、靜態成員和類的普通成員一樣,也有public、protected、private,3種訪問級別,也可以具有返回值,const修飾符等參數。

C++11的成員初始化

C++11支持非靜態成員變量在聲明時,直接初始化

class A
{
public:
 void Print()
 {
 cout << a << endl;
 cout << b._b<< endl;
 cout << p << endl;
 }
private:
 // 非靜態成員變量,可以在成員聲明時,直接初始化。
 int a = 10;
 B b = 20;
 int* p = (int*)malloc(4);
 static int n;
};

友元

友元函數

在重載運算符中,我們沒辦法將operator<<重載成員成員函數。因爲cout的輸出流對象和隱含的this指針在搶佔第一個參數位置。this指針默認是第一個參數也就是左操作數了。但是實際中使用cout需要是第一個形參對象,才能正常使用。所以我們要將operator<<重載成全局函數。但是這樣的話,又會導致類外沒有辦法訪問成員,那麼這裏就需要友元來解決了。operator同理。

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

#include <iostream>    
using namespace std;    
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& operator<<(ostream& _cout,const Date& d)    
{    
  _cout<<d._year<<"-"<<d._month<<"-"<<d._day;    
  return _cout;    
}    
//這裏不能加const,如果加了const就不能對對象d的成員變量進行修改了    
istream& operator>>(istream& _cin,Date& d)    
{    
  _cin>>d._year;    
  _cin>>d._month;
  _cin>>d._day;
  return _cin;
}
int main()
{
  Date d(2017,12,24);
  cin>>d;
  cout<<d<<endl;
  return 0;
} 

友元函數說明:

1、友元函數可訪問類的私有成員,但不是類的成員函數

2、友元函數不能用const修飾

3、友元函數可以在類定義的任何地方聲明,不受類訪問限定符限制

4、一個函數可以是多個類的友元函數

5、友元函數的調用與普通函數的調用和原理相同

友元類

友元類的所有成員函數都可以是另一個類的友元函數,都可以訪問另一個類中的非公有成員。

  • 友元關係是單向的,不具有交換性

    有A類和B類,在A中聲明B類爲其友元類,那麼可以在B類中直接訪問A類的私有成員變量,但想在A類中訪問B類中私有的成員變量則不行

  • 友元關係不能傳遞

    如果B是A的友元,C是B的友元,則不能說明C是A的友元

內部類

如果一個類定義在另一個類的內部,這個內部類就叫做內部類。注意此時這個內部類是一個獨立的類,它不屬於外部類,更不能通過外部類的對象去調用內部類。外部類對內部類沒有任何優越的訪問權限。

內部類是外部類的友元類。

內部類特性

1、內部類可以定義在外部類的public、protected、private都是可以的。

2、注意內部類可以直接訪問外部類中的static、枚舉成員,不需要外部類的對象/類名。

3、sizeof(外部類)=外部類,和內部類沒有任何關係。

牛客的一道小練習

求1+2+3+…+n,要求不能使用乘除法、for、while、if、else、switch、case等關鍵字及條件判斷語句(A?B:C)。

https://www.nowcoder.com/practice/7a0da8fc483247ff8800059e12d7caf1?tpId

基本上我們能想到的方法都被限制了,那麼這時候就可以考慮構造函數每次調用時都會+1

class Solution {
public:
    
    class Sum
    {
        public :Sum()
        {
            _sum += _i;
            _i++;
        }
    };
        
    int Sum_Solution(int n) {
        _i = 1;
        _sum = 0;
        Sum array[n];
        return _sum;
    }
    static size_t _sum;
    static size_t _i;
};
    size_t Solution::_sum = 0;
    size_t Solution::_i = 0;
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章