類定義是以關鍵字class
開頭,后面跟類的名稱。主體是包含在一對花括號中。類定義后必須跟著一個分號或一個聲明列表。
類的對象的公共數據成員可以使用直接成員訪問運算符.
來訪問。需要注意的是,私有的成員和受保護的成員不能直接使用成員訪問運算符來訪問。
類成員函數
類的成員函數是指把定義和原型寫在類定義內部的函數。類成員函數是類的一個成員,他可以操作類的任意對象,可以訪問對象中的所有成員。
成員函數可以定義在類定義內部,或者單獨使用范圍解析運算符::來定義,在類定義中定義的成員函數把函數聲明為內聯的,即使沒有使用inline
標識符。聲明必須寫在類的內部。
在類外定義的格式為:
數據類型 類名::方法名(參數列表) {}
類訪問修飾符
數據封裝是面向對象編程的一個重要特點,它防止函數直接訪問類類型的內部成員。類成員的訪問限制是通過在類主體內部對各個區域標記訪問修飾符public private protected
來指定的。
一個類可以有多個訪問修飾符標記區域,每個標記區域在下一個標記區域開始之前或者遇到類主體結束右括號之前都是有效的。
成員和類的默認訪問修飾符是private
- 公有
public
:公有成員在程序中類的外部是可訪問的。您可以不適用任何成員函數來設置和獲取公有變量的值。 - 私有
private
:已有成員變量或函數在類的外部是不可訪問的,甚至是不可查看的,只有類和友元函數可以訪問私有成員。默認情況下,類對所有成員都是私有的。
實際操作中,我們一般會在私有區域定義數據,在公有區域定義相關的函數,以便在類的外部也可以調用這些函數。 - 保護
protected
:保護成員變量或函數與私有成員十分相似,但有一點不同,保護成員在派生類(即子類)中是可訪問的。
對于一個空類,編譯器默認產生4個成員函數:默認構造函數、析構函數、拷貝構造函數和賦值函數。
還有關于繼承中訪問權限問題:傳送門
類構造函數&析構函數
類的構造函數時類的一種特殊的成員函數,他會在每次創建類的新對象時執行。
構造函數的名稱與類名是完全相同的,并且不會返回任何返回類型,也不會返回void,構造函數可用于為某些成員變量設置初始值。如果需要,構造函數也可以帶有參數。
當類中未定義構造函數時,編譯器會自動假設存在兩個默認構造函數。
類名:類名() {}
類名:類名(const 類名&a){} //沒有什么用
如果自己定義了構造函數,則默認的構造函數不會存在。
構造函數可以被重載。
可以使用初始化列表來初始化字段,例如:
class C
{T X,Y,Z;C();
}
C::C(T a,T b,T c):X(a),Y(b),Z(c)
{...
}
類的析構函數是類的一種特殊的成員函數,他會在每次刪除所創建的對象時執行。析構函數的名稱與類對 名稱是完全相同的,只是在前面加了~
作為前綴,他不會返回任何值,也不能帶任何參數。
析構函數不能重載,如果沒有寫析構函數,C++會自動幫我們寫一個析構函數。
拷貝構造函數
拷貝構造函數是一種特殊的構造函數,在創建對象時,是使用同一類中之前創建的對象來初始化新創建的對象。拷貝構造函數通常用于
- 復制對象把它作為參數傳遞給函數
- 復制對象,并從函數返回這個對象
- 通過使用另一個同類型的對象來初始化新建的對象(拷貝初始化)
如果類沒有定義拷貝構造函數,編譯器會自行定義一個,如果類帶有指針變量,并由動態分配內存,則它必須有一個拷貝構造函數(否則會引發錯誤)。
最常見的形式如下:
classname (const classname &obj)
{//主體
}
這里對拷貝初始化進行進一步的說明:
A x(y); //直接初始化,如果是類類型將調用構造函數
A x=y; //拷貝初始化,如果是類類型將調用拷貝構造函數
值包含類類型成員或者內置類型(不包含指針類型)成員的類無須顯式地定義拷貝構造函數也可以進行拷貝。當類的成員函數包含指針或者是成員表示在構造函數中分配的其他資源時,就必須定義拷貝構造函數。
友元函數
友元函數是定義在類外部,但是有權訪問類的所有私有成員和保護成員,如果不是static成員則需要對象作為參數,如果訪問static成員則不需要參數的函數,盡管友元函數的原型有在類的定義中出現過,但是友元函數并不是成員函數。
友元可以是一個函數,該函數稱為友元函數;友元可以是一個類,該類稱為友元類。在這種情況下,整個類及其所有成員都是友元。如果要聲明函數為一個友元函數,需要在類定義中該函數原型前使用關鍵字friend
.
class A
{friend 返回類型 函數名B(參數列表);
};
返回類型 B(參數列表)//請注意,A不是任何類的成員函數
{}
int main()
{A a; B(參數列表);//對友元函數的調用不需要對象和類
}
聲明類B的所有成員為另一個類A的友元則需要在A的定義專用加上以下聲明:
class A
{...friend class B;
}
同樣在友元類中我們也可以通過對象參數訪問保護和私有成員。
內聯函數
內聯函數通常與類一起使用,如果一個函數是內聯的,那么在編譯時,編譯器會把該函數的代碼副本放置在每個調用該函數的地方。對內聯函數進行修改都要重新編譯函數的所有客戶端,因為編譯器需要更換一次所有的代碼。
如果想要把一個函數定義為內聯函數,則需要在函數定義前面放置關鍵字inline
。如果已定義的函數多于十行,編譯器會忽略inline
限定符。
在類定義中的函數都是內聯函數,即使沒有使用內聯函數。
- 在內聯函數內不允許使用循環語句和開關語句