北京到安陽的火車票灰色行業(yè)關鍵詞優(yōu)化
10.2.2 C++中的類
類是一種將抽象轉換未用戶定義類型的C++工具,它將數(shù)據(jù)表示和操作數(shù)據(jù)的方法合成一個整潔的包。
接口:一個共享框架,供兩個系統(tǒng)交互時使用。
1.訪問控制
使用類對象的程序可以直接訪問類的公有部分,但只能通過公有成員函數(shù)訪問對象的私有成員
防止程序直接訪問數(shù)據(jù)被稱為數(shù)據(jù)隱藏。
數(shù)據(jù)隱藏不僅可以防止直接訪問數(shù)據(jù),而且還讓開發(fā)者無需了解數(shù)據(jù)是如何被表示的。
將實現(xiàn)細節(jié)放在一起并將它們與抽象分開稱為封裝
2.private和public
在類中使用private來強調(diào)成員是私有的,public強調(diào)成員是公有的。
在class聲明的類中,成員默認是私有的,而在struct中成員默認是公有的。
10.2.3實現(xiàn)類的成員函數(shù)
定義成員函數(shù)時,使用作用域解析運算符::來來標識函數(shù)所屬的類
類方法可以訪問類的private組件
如stock是一個類名,它有一個叫fun的成員函數(shù)
void stock::fun()
{
。。。。
}
1.內(nèi)聯(lián)函數(shù)
定義在類聲明中的函數(shù)都將自動成為內(nèi)聯(lián)函數(shù),類聲明常將短小的成員函數(shù)作為內(nèi)聯(lián)函數(shù),如果想在類外聲明內(nèi)聯(lián)函數(shù),可以使用inline關鍵字。
內(nèi)聯(lián)函數(shù)要求每個使用它們的文件中都對其進行定義,為了方便使用內(nèi)聯(lián)函數(shù),我們將內(nèi)聯(lián)函數(shù)放在類的頭文件中。
2.方法使用哪個對象
創(chuàng)建對象: 類名 對象名(類名相當于一種數(shù)據(jù)類型 對象名是變量)
使用成員函數(shù)方法 對象名.函數(shù)名(參數(shù))
10.3類的構造函數(shù)和析構函數(shù)
對象的變量不能像初始化int變量 那樣來進行初始化,因為對象的存在私有成員,在類外無法進行訪問。而類的成員函數(shù)可以訪問這些成員變量,因此我們可以使用類的成員函數(shù)對對象進行初始化,而類的構造函數(shù)就是C++用來初始化對象的一個函數(shù)。
構造函數(shù)在創(chuàng)建對象的時候會被自動調(diào)用。
構造函數(shù):
名字必須與類名一致,且沒有返回類型,可以有參數(shù),可以重載(也就是可以有多個構造函數(shù))。如fun類的構造函數(shù)為 fun();
若不定義構造函數(shù),程序將提供一個默認的隱藏的構造函數(shù),而這個構造函數(shù)并不進行任何操作。若手動定義了多個構造函數(shù),
程序則會根據(jù)定義對象時候括號里的參數(shù),來確定使用哪一個構造函數(shù)。
如果提供了非默認的構造函數(shù),下列語句會出錯
fun A;定義一個fun類的對象A?
有兩種方法可以解決這個問題,一是在類里加入一個默認的構造函數(shù),二是給非默認的構造函數(shù)提供默認參數(shù)。
但是這兩種方法不能同時用,如果同時用的話,fun A;可以使用任意一個構造函數(shù),于是程序將不知道使用哪一個,會爆錯。
列表初始化
聽名字就是列一個表進行初始化
語法就是下面這種
-
#include <iostream>
-
using namespace std;
-
class A
-
{
-
int w;
-
public:
-
A(int j=0):w(j){}
-
};
-
int main()
-
{
-
A a;
-
return 0;
-
}
在函數(shù)名后加一個分號然后寫出變量名 ,變量名后跟一個括號,意思是用括號里這個值來初始化這個變量
注意事項:
- 這種格式只能用于構造函數(shù)
- 必須用這種格式來初始化非靜態(tài)const數(shù)據(jù)成員和引用數(shù)據(jù)成員
什么時候初始化列表是必用的呢?
1. 類成員為const類型
2. 類成員為引用類型
-
#include <iostream>
-
using namespace std;
-
class A
-
{
-
public:
-
A(int &v) : i(v), p(v), j(v) {}
-
void print_val() { cout << "hello:" << i << " " << j << endl;}
-
private:
-
const int i;
-
int p;
-
int &j;
-
};
-
int main()
-
{
-
int pp = 45;
-
A b(pp);
-
b.print_val();
-
}
構造函數(shù) 所說是起到初始化的作用,但是實際上是通過賦值的操作來進行初始化的,但是const變量 和引用無法通過賦值來進行初始化,所以要用初始化列表。
3. 類成員為沒有默認構造函數(shù)的類類型
-
#include <iostream>
-
using namespace std;
-
class Base
-
{
-
public:
-
Base(int a) : val(a) {}
-
private:
-
int val;
-
};
-
class A
-
{
-
public:
-
A(int v) : p(v),b(v) {}
-
void print_val() { cout << "hello:" << p << endl;}
-
private:
-
int p;
-
Base b;
-
};
-
int main()
-
{
-
int pp = 45;
-
A b(pp);
-
b.print_val();
-
}
原因同樣是創(chuàng)建對象時,要初始類成員的每一個成員
(如果沒有在初始化列表里面,編譯器會自動使用它的默認的構造函數(shù)進行初始化,但是它沒有默認構造函數(shù),所以會編譯報錯,所以沒有默認構造函數(shù)的成員變量需要使用初始化列表進行初始化)
這里如果把初始化列表里的b刪掉,就會爆錯,同理類存在繼承關系,派生類必須在初始化列表里初始化。
4.?如果類存在繼承關系,派生類必須在其初始化列表中調(diào)用基類的構造函數(shù)
PS:若一個類中有其他類的對象,那么該如何初始化這個類呢?
只需在類的構造函數(shù)的初始化列表里加上其他類對象的名字及其參數(shù)列表即可。
派生類構造函數(shù)的執(zhí)行順序:
①?調(diào)用基類構造函數(shù),初始化基類數(shù)據(jù)成員;
②?調(diào)用子對象構造函數(shù),初始化子對象數(shù)據(jù)成員;
③?執(zhí)行派生類自身的構造函數(shù),初始化自己新增數(shù)據(jù)成員。
析構函數(shù)
析構函數(shù)的特點:
- 一個類只有一個析構函數(shù),不能重載
- 名字與類名相同,定義時候要加上~
- 沒有參數(shù)
- 不能有返回值,沒有返回值類型
對應于構造函數(shù)初始化對象,析構函數(shù)是用來釋放對象的內(nèi)存的,可以將delete等操作放在析構函數(shù)里,析構函數(shù)在對象離開其作用域的時候自動執(zhí)行。
對象析構的順序和創(chuàng)建的順序相反,即先構造的后析構,后構造的先析構
但這并非絕對成立!!!!
在不同的作用域中的對象,或者具有不同存儲類別的對象,調(diào)用構造函數(shù)和析構函數(shù)的順序也會有所不同
- 一個程序中有多個文件。在多個文件中定義了全局對象,那么這些對象的執(zhí)行順序是不確定的;
- 在函數(shù)中定義局部自動對象,如果函數(shù)被多次調(diào)用;多次調(diào)用構造函數(shù)和析構函數(shù);
- 如果函數(shù)中定義靜態(tài)局部對象;那么函數(shù)調(diào)用結束時對象并不釋放,只有main結束或調(diào)用exit時才調(diào)用析構函數(shù)。
?
什么時候調(diào)用析構函數(shù)?
- 如果在函數(shù)中定義了一個對象,當函數(shù)調(diào)用結束時,釋放對象前自動執(zhí)行析構函數(shù)
- static 局部對象在函數(shù)調(diào)用結束時,包含的對象不會被釋放,只在main函數(shù)結束或調(diào)用exit函數(shù)時,才調(diào)用static局部對象的析構函數(shù)。
- 如果定義了一個全局對象,則在程序的流程離開其作用域時(如main函數(shù)結束,或exit語句),調(diào)用該全局對象的析構函數(shù)
- 如果用new運算符動態(tài)地建立了一個對象,當用delete 運算符釋放對象時,先調(diào)用該全局對象的析構函數(shù)。
10.4this指針
眾所周知,同一個類的多個對象公用一套方法,那么在調(diào)用同一套方法的時候,程序是如何知道要訪問哪個對象里的成員的呢,答案是通過this指針,類的成員函數(shù)里有一個隱藏的指向對象的參數(shù)就是this指針。
具體看下面這個例子
-
#include <iostream>
-
using namespace std;
-
class Base
-
{
-
public:
-
Base(int a) : val(a) {}
-
void display();
-
private:
-
int val;
-
};
-
void Base::display()
-
{
-
cout<<val<<endl;//實際上就是cout<<this->val<<endl;
-
}
-
int main()
-
{
-
Base a(1),b(2);
-
a.display();//看上去沒有傳參數(shù),實際上傳了a的地址
-
}
?
10.5對象數(shù)組
對象數(shù)組跟結構體差不多,這里就講講一些不同點。
首先是初始化,由于對象有構造函數(shù),所以我們在初始化對象數(shù)組的時候要用大括號括起來,將構造函數(shù)列出來,來進行初始化
例如
-
const int max=4;
-
fun a[max]={ fun(1),fun(2),fun(3),fun(5)}
-
如果類只有一個成員變量,則可以直接像數(shù)組那樣賦值
-
如:fun b[max]={1,2,3,4};
10.6對象指針
什么是對象指針?
創(chuàng)建一個類的對象時,系統(tǒng)會為每一個對象分配一定的存儲空間,以存放成員。對象空間的起始地址就是對象的指針??梢远x一個指針,用來存放對象的指針。
語法
-
time *pt;
-
time t;
-
pt=&t1; // 指針指向對象
對象指針的使用與普通指針使用差不多,具體可以自行百度指針的使用