转载自《C++ exceptional style》第22条
隐藏经常发生在继承关系中,派生类重新定义了基类的非virtual函数,当发生隐藏时,编译器名字隐藏机制如下:
1. 编译器会从当前域开始查找(比如派生类对象调用,会在派生类的定义内查找),查找需要的名字;
2. 如果在当前域没有找到,编译器会在外围作用域继续查找,先是基类的定义内,然后是全局名字空间;
3. 一旦在某个作用域内包含需要的名字就会停下来,并就该作用域内的名字进行决议,这意味着往外层的作用域就不予考虑了,从而将外层作用域的同名函数隐藏;
4.编译器在当前的名字空间中找到与所求名字同名的实体之间进行决议(函数重载),如果选不出最优,就产生二义性错误;
5. 选出最优的函数,查看函数是否可以访问/调用
//例子 名字隐藏了new
class Base
{
public:
static void* operator new(std::size_t, const FastMemory&);
};
class Derived: public Base
{
Derived *p1 = new Derived; //错误,无可用的匹配,因为简单new被隐藏
Derived *p2 = new(std::nothrow) Derived; //错误,无可用的匹配,因为nothrow new被隐藏
void *p3 = /* 足够放下一个Derived对象 */
new(p3) Derived; //错误,无可用的匹配,因为定位new被隐藏
FastMemroy f;
Derived *p4 = new(f) Derived; //调用Base::operator new()
}
//首先编译器在Derived类内查找new函数,没有找到名字;
//编译器往外一层查找new,在基类Base定义内查找,找到了new函数,就不继续考虑全局空间的定义了
//基类只定义了一个new运算符,把简单new,定位new和nothrow new都隐藏了,导致无匹配的版本可使用