在两个完全相同的名称的名称查找中使用声明的效果
effects of using declaration on name lookup for two exactly same names
基本上,我的问题与名称查找和using
声明有关(http://en.cppreference.com/w/cpp/language/namespace)
假设我们有以下(绝对愚蠢的)代码:
class Base {
public:
void fun()
{std::cout << "Base fun" << std::endl;}
};
class Derived : public Base {
public:
// Here both names "fun" are visible or not?
using Base::fun;//let's call this func_1
void fun() //let's call this func_2
{
std::cout << "Derived fun" << std::endl;
}
};
Derived d;
d.fun(); // This resolves to func_2, why?
因此,我的理解是,现在我们应该让两个名称都可见,然后对于名称查找,应该存在一些歧义。但事实并非如此。原因是什么?或者换句话说,我是否误解了一些概念?
对于这种情况,标准有一个特殊的规则。
当using声明将基类中的名称带入派生类作用域时,成员函数和派生类中的成员函数模板覆盖和/或隐藏成员函数和成员函数具有相同名称、参数类型列表(8.3.5)、cv资格和ref限定符(如果有)的模板基类(而不是冲突的)。
([namespace.udcl]/15)
请注意,与往常一样,您可以通过执行d.Base::fun()
来强制调用Base::fun
。
您引用的链接是针对namespace
的,您应该使用声明来引用class
,其中声明:
如果派生类已经有一个具有相同名称、参数列表和资格的成员,则派生类成员将隐藏或重写(与基类引入的成员不冲突)。
在您发布的代码的情况下,Base
中的void fun()
被Derived
中的void fun()
隐藏,所以不,它们都不"可见",除非您在调用fun
时是明确的,例如:
class Base {
public:
void fun() { std::cout << "base" << std::endl; }
};
class Derived : public Base {
public:
using Base::fun;
void fun() { std::cout << "derived" << std::endl; }
};
Derived d;
d.fun(); // name lookup calls Derived::fun
d.Base::fun(); // explicitly call Base::fun
此外,由于您已经公开派生自Base
,严格地说,您不需要using
声明;在void fun()
是Base
中的protected
的情况下,或者private
/protected
是从Base
继承的,例如:
#include <iostream>
class Base {
public:
void fun() { std::cout << "base" << std::endl; }
protected:
void fun2() { std::cout << "base2" << std::endl; }
};
// class default is private
class Private : Base {
public:
// fun() won't be accessible since private inheritance and no using
// fun2 can now be accessed directly
using Base::fun2;
};
class Public : public Base {
public:
// fun is already public
using Base::fun2; // bring into scope
};
class Derived : public Base {
public:
using Base::fun;
using Base::fun2;
// overriden method fun, no conflict, choose this method if type is Derived
void fun() { std::cout << "derived" << std::endl; }
};
int main(int argc, char* argv[])
{
Private p;
Public u;
Derived d;
// generates a compiler error since Base is privately inherited
//p.fun();
p.fun2(); // OK, output: base2
u.fun(); // OK, output: base
u.fun2(); // OK, output: base2
// use Derived::fun since override
d.fun(); // OK, output: derived
d.Base::fun(); // OK, output: base
d.fun2(); // OK, output: base2
return 0;
}
希望这能帮助
相关文章:
- 查找声明为结构类型 C++ 的数组末尾
- 假设声明中某些上下文中需要的名称查找规则是什么
- 哪里定义了查找名称最直接声明的名称查找规则
- 无法转发声明C typedef结构-正在查找其他建议
- C++中成员名称查找和访问声明中的歧义
- 为什么名称查找在找到使用 using 指令隐式声明的实体时不停止?
- 为什么在其他函数中声明的函数不参与参数相关查找?
- 查找已声明但未定义的函数
- 查找声明全局变量的文件
- P/调用,查找/声明函数入口点时遇到问题
- 查找没有定义的方法声明
- 声明一个字符串数组并查找其中的元素数量(openFrameworks)
- 在libclang(Python)中查找特定函数声明的所有引用
- 如何在Visual Studio/C++/.NET中快速查找给定声明所需的头文件
- 3.4.1/6 是否忽略了在函数的参数声明子句中找到的函数中使用的名称的查找?
- 在两个完全相同的名称的名称查找中使用声明的效果
- C++受模板方法声明影响的名称查找
- 在 Clang AST 中查找声明的父级
- clang与gcc在查找声明方面有何不同
- 如何查找声明名称空间变量的文件