1、名稱查找
受限名稱的名稱查找在作用域內部進行,不考慮它的外圍作用於(但是如果作用域是類,查找範圍可以是它的基類)。
非受限名稱可以由內至外在所有外圍類中查找。先查找該類和基類,然後查找外圍類的作用域,也成爲普通查找(含有ADL)。
ADL(argument-dependent lookup)依賴於參數的查找,如果名稱後面的括號裏有一個或多個實參表達式,那麼將查找這些實參的associated class(關聯類)和assoicated namespace(關聯名字空間)有以下規則:
(1)對於基本類型,該集合爲空。
(2)對於指針和數組,該集合是所引用類型的associated class和assoicated namespace
(3)對於枚舉,assoicated namespace是枚舉聲明所在的namespace。對於類成員,associated class指它所在的類
(4)對於class類型,associated class包括本身、外圍類型、直接基類、間接基類。assoicated namespace是class所在的namespace。如果這個類是一個類模版實例化體,還包含:模版類型參數本身的類型、聲明模版的模版實參所在的class和namespace。
(5)對於函數類型,包括所有參數和返回類型的assoicated namespace和associated class。
2、名稱插入
友元名稱插入
參考書中例子
template<typename T>
class C
{
friend void f();
friend void f(C<T> const&);
};
void g(C<int> *p)
{
f();<span style="white-space:pre"> </span>/*此處不可見*/
f(*p);<span style="white-space:pre"> </span><span style="font-family: Arial, Helvetica, sans-serif;">/*此處可見*/</span>
}
在類中的友元函數首次聲明,通常而言,友元的聲明在外不可見。但是,友元函數所在類屬於ADL的關聯類集合,可以通過參數找到。
插入式類名稱
在類本身作用域中插入該類名稱。
還是書中的例子
int C;
class C
{
private:
int i[2];
public:
static int f(){
return sizeof(C);
}
};
int f()
{
return sizeof(C);
}
int main()
{
std::cout << "C::f() = " << C::f() << ","<span style="white-space:pre"> </span>//返回類型C
<< "::f() = " << ::f() << std::endl;<span style="white-space:pre"> </span>//返回變量C
}
3、解析模版
依賴型類型名稱
比如Trap<T>::x *y
在某些時候會被解析爲x*y,需要加關鍵字typename
規則:
(1)名稱出現在一個模版中
(2)名稱是受限的
(3)名稱不是用於指定基類繼承的列表中,也不是構造函數的成員初始化列表中
(4)名稱依賴於模版
例子在P127
依賴型模版名稱
如果限定符號前面的名稱的類型要依賴於某個函數模版,並且緊接在限定符後面的是一個template-id,那麼就需要用關鍵字template
template<typename T>
class Shell
{
public:
template<int N>
class In
{
public:
template<int M>
class Deep
{
virtual void f();
};
};
};
//當p是Shell的一個對象的時候,表達式爲
p.template Deep<N>::f()
3、派生和類模版
非依賴型基類
重點:對於模版中的非依賴性基類而言,如果在它的派生類中查找一個非受限名稱,那就會先查找這個非依賴型基類,然後才查找模版參數列表。
例子P131.
依賴型基類
能有this->前綴的地方用前綴
在派生類中添加using-declaration
詳細P133
學習的書籍爲《C++ Templates 中文版》(人民郵電出版社)
所有原文和書上範例都來自於此