文章目錄
- 再談構造函數
- 初始化列表
- static
- 概念:
- 友元
- 友元函數
- 友元類
- 內部類
- 再次理解類和對象
再談構造函數
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){}
private:int _year;int _month;int _day;
};
1,成員對象在初始化列表只能出現一次,
2,類中包含以下情況必須用初始化列表初始化
1,const 修飾
2, 引用
3,自定義類型(無默認構造函數的)
class A
{
public:A(int a):_a(a){ }
private:int _a;
};
class B
{
public:B(int b, int ret,int obj):_b(b), _ret(ret), _obj(obj){}
private:const int _b;int& _ret;A _obj;
};
🚩 3,盡量使用列表初始化,因為無論是否使用列表初始化,自定義類型都會先進行列表初始化。
🚩 4,成員變量的聲明次序就是初始化列表的初始化順序,與初始化的列表順序無關,
試問以下代碼輸出什么?
#include <iostream>
using namespace std;
class A
{
public:A(int a):_a1(a), _a2(_a1){}void print(){cout << _a1 << " " << _a2;}
private:int _a2;int _a1;
};int main()
{A aa(1);aa.print();return 0;
}
1 隨機值
因為聲明順序先_a2,再a1。 初始化時_a1隨機值賦給了_a2,而_a1得到1,
static
概念:
聲明static的類成員叫靜態成員,用static修飾的成員變量叫靜態成員變量,用static修飾的成員函數叫靜態成員函數,靜態成員變量一定要在類外初始化
#include <iostream>
using namespace std;
class A
{
public:A(){_scount++;}A(const A& a){_scount++;}static int Getscount(){return _scount;}~A(){--_scount;}
private:static int _scount;
};int A::_scount = 0;int main()
{cout << A::Getscount() << endl;A a1, a2;A a3(a1);cout << A::Getscount() << endl;return 0;
}
0
3
🚩1,靜態成員為所有類對象所共享,不屬于某個具體的類對象,存在靜態區,所有對象都能調用
2,靜態成員變量必須在類外定義,定義時不需要static,類中只是聲明
3,靜態成員可以用類名::加靜態成員訪問,也可以類對象.加靜態成員訪問,
4,靜態成員函數沒有this指針,不能訪問任何非靜態成員,
5,類中的靜態成員也受到public,private限制
問題:
1,靜態成員函數可以調用非靜態成員函數嗎?
不可以,無this指針,非靜態成員函數必須通過類對象調用(因為可能訪問對象的成員變量)
2,非靜態成員函數可以調用靜態成員函數嗎?
可以,靜態成員函數全局共享,都可以用,
友元
友元提供了一種突破封裝的模式,提供了便利,但使用友元會增加耦合度,所有友元不宜多用,
友元分為:友元函數,友元類,
友元函數
#include <iostream>
using namespace std;
class A
{
public:A(int hour = 10, int minute = 30):_hour(hour),_minute(minute){}ostream& operator<<(ostream& _cout){_cout << _hour <<'-'<< _minute << endl;return _cout;}
private:int _hour;int _minute;
};
int main()
{A a1,a2;a1 << cout; return 0;
}
a1<<cout -> a1.operator<<(&a1,cout)
不符合常規調用,
但是有this指針,所以又不能反過來調用,因為cout<<a1,this指針會和cout搶位置,
🚩實際應用中,cout要在第一個形參位置,所以要將operator重載為全局函數,但是全局函數又訪問不了私有成員,所以我們用到友元
🚩友元函數是定義在類外部的普通函數,可以直接訪問類的私有成員,不屬于任何類,但是要在類內部聲明,聲明時前面加friend,
#include <iostream>
using namespace std;
class A
{friend ostream& operator<<(ostream& _cout, const A& a);friend istream& operator>>(istream& _cin, A& a);
public:A(int hour=10,int minute=40):_hour(hour), _minute(minute){ }private:int _hour;int _minute;
};
ostream& operator<<(ostream& _cout, const A& a)
{_cout << a._hour <<"-" << a._minute << endl;return _cout;
}
istream& operator>>(istream& _cin, A& a)
{_cin >> a._hour >> a._minute;return _cin;
}
int main()
{A a1, a2;cin >> a2;//14 20cout << a1 << a2;return 0;
}
14-20
10-40
說明:
1,友元函數可以直接訪問類的私有和保護成員,但不是類的成員函數,
2,友元函數不能被const修飾,
3,友元可以定義在類的任何位置,不受訪問限定符限制
4,一個函數可以被多個類友元,
5,友元函數和普通函數調用相同,
友元類
🚩 1,A類是B類的友元,則A可以訪問所有B的私有成員變量,但反過來不行。
🚩 2,友元無傳遞性,A類是B類的友元,B是C的友元,但A不能訪問C類的私有變量,
class Time
{friend class Date;
public:
private:int _hour;int _minute;
};class Date
{
public:void settime(int hour, int minute){_t._hour = hour;_t._minute = minute;}
private:int _year;int _month;int _day;Time _t;
};
內部類
:一個類如果定義在另一個類的里面,就叫內部類,內部類屬于獨立的類,它不屬于外部的類,更不能通過外部類訪問內部類的成員變量,外部類對內部類沒有任何優越權限
注意:
內部類就是外部類的友元,但外部類不是內部的友元
特性
1,內部類可以定義在外部類任何位置,不受訪問限定符限定
2,內部類可以直接訪問外部的static成員,不需要加類名和.
3,sizeof(外部類)=外部類,和內部類無關
#include <iostream>
using namespace std;
class A
{
public:class B{public:void test(const A& a){cout << k << endl;cout << a.h << endl;}private:};
private:static int k;int h=2;
};
int A::k = 3;
int main()
{A::B t;t.test(A());//隱式對象return 0;
}
再次理解類和對象
總結:類是對某一類實體對象進行描述的,描述對象的各種屬性,描述完成后就形成一種新的自定義類型,再通過自定義類型實例化具體對象