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 }
依赖型类型名称
比如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()
非依赖型基类
重点:对于模版中的非依赖性基类而言,如果在它的派生类中查找一个非受限名称,那就会先查找这个非依赖型基类,然后才查找模版参数列表。
例子P131.
依赖型基类
能有this->前缀的地方用前缀
在派生类中添加using-declaration
详细P133
学习的书籍为《C++ Templates 中文版》(人民邮电出版社)
所有原文和书上范例都来自于此