1. 類型別名作為成員(P243
除了定義數據和函數成員之外,類還可以自定義某種類型在類中的別名。
由類定義的類型名字和其他成員一樣存在訪問限制,
可以是public或者private中的一種。
class A
{
public:
typedef std::string::size_type type_s;
private:
type_s a = 0;
};
我們在A
的public部分定義了type_s
,
這樣用戶就可以使用這個名字了A::type_s
。
2. 類型的static成員(P269
我們通過在成員的聲明之前加上關鍵字static,使之與類關聯在一起。
和其他成員一樣,靜態成員可以是public的或private的。
類的靜態成員存在于任何對象之外,對象中不包含任何與靜態數據成員有關的數據。
類似的,靜態成員函數也不與任何對象綁定在一起,它們不包含this指針。
class A
{
public:
const static int a = 0;
};
int main()
{
int b = A::a;
return 0;
}
3. 模板類型參數的類型成員(P593
以上我們用作用域運算符::
,來訪問類型成員和static成員。
在普通代碼中,編譯器掌握類的定義,
因此,它知道通過作用域運算符訪問的名字是類型還是static成員。
例如,string::size_type
是一個類型,因為編譯器知道string
的定義。
但對于模板代碼就存在困難,例如假定T
是一個模板類型參數,
當編譯器遇到類似T::a
這樣的代碼時,
它不會知道a
是一個類型成員還是一個static數據成員,直到實例化時才會知道。
但是為了處理模板,編譯器必須知道名字是否表示一個類型。
例如,T::size_type * p
,編譯器需要知道,
我們是正在定義一個名為p
的變量,
還是將一個名為size_type
的static數據成員與名為p
的變量相乘。
默認情況下,C++語言假定通過作用域運算符訪問的名字不是類型,
因此,如果我們希望使用一個模板類型參數的類型成員,
就必須顯式告訴編譯器該名字是一個類型。
我們通過使用關鍵字typename
來實現這一點。
template <typename T>
typename T::value_type top(const T &c) // 返回一個T::value_type類型
{
if (!c.empty())
{
return c.back();
}
return typename T::value_type(); // 調用T::value_type類型的構造函數
}