我在 C++ 继承方面遇到了问题.
I'm having a problem with C++ inheritance.
我有一个类层次结构:
class A {
public:
virtual void onFoo() {}
virtual void onFoo(int i) {}
};
class B : public A {
public:
virtual void onFoo(int i) {}
};
class C : public B {
};
int main() {
C* c = new C();
c->onFoo(); //Compile error - doesn't exist
}
我的问题是:为什么不编译?我的理解是 C 应该从 A 继承两个 onFoo 函数——事实上,如果你删除 B 中 onFoo 的重新定义,这会编译——但是 g++ 给出了一个错误,表明 C 没有 onFoo() 函数.
My question is: why doesn't this compile? My understanding is that C should inherit both onFoo functions from A - and in fact, this compiles if you remove the redefinition of onFoo in B - but g++ gives an error that C has no onFoo() function.
您遇到的问题与名称查找在 C++ 中的工作方式有关.特别是,在解析成员时,编译器将查看正在访问该成员的对象的静态类型.如果在该类中找到标识符,则查找完成并且(在成员函数的情况下)重载解析开始.如果未找到标识符,它将逐个类爬上层次结构,尝试一次定位一个标识符.
The issue that you are experiencing is related to how name lookup works in C++. In particular, when resolving a member, the compiler will look into the static type of the object on which the member is being accessed. If the identifier is found in that class, then lookup completes and (in the case of member functions) overload resolution starts. If the identifier is not found, it will crawl up the hierarchy, class by class, trying to locate the identifier one level at a time.
在您的特定情况下,您有 c->onFoo();
并且 c
是 C
类型.编译器在 C
中看不到任何 onFoo
声明,因此它在层次结构中继续向上.当编译器检查 B
时,它看到在该级别有一个 void onFoo(int i)
声明,因此它停止查找,并尝试重载解析.此时由于参数不一致导致重载解析失败.
In your particular case, you have c->onFoo();
and c
is of type C
. The compiler does not see any declaration of onFoo
in C
, so it continues upwards in the hierarchy. When the compiler checks B
, it sees that there is a declaration of void onFoo(int i)
at that level, so it stops lookup, and tries overload resolution. At this time, the overload resolution fails due to the inconsistency in the arguments.
void onFoo(int)
声明存在于 B
级别这一事实具有隐藏其余重载的效果在任何基类中,因为它将停止查找.请注意,这是非限定查找的问题,该函数仍然存在并适用于该对象,但不会被常规查找找到(您仍然可以将其称为 c->A::onFoo()
).
The fact that a declaration of void onFoo(int)
is present at B
level has the effect of hiding the rest of the overloads in any base class, as it will stop lookup. Note that this is a problem with unqualified lookup, the function is still there and applicable to the object, but will not be found by regular lookup (you can still call it as c->A::onFoo()
).
至于如何处理隐藏,最简单的方法是使用using声明将函数带入作用域:
As of how to deal with hiding, the simplest way is by employing the using declaration to bring the functions into scope:
class B : A {
public:
using A::onFoo; // All A::onFoo overloads are *considered* here
void onFoo( int );
};
这里的using
声明的作用是,当查找B
类时,在搜索onFoo
标识符时,编译器指示还要考虑基类中 onFoo
的所有重载,从而启用常规查找以找到 A::onFoo()
.
The effect of the using
declaration here is that when the B
class is looked up, in search for the onFoo
identifier, the compiler is instructed to also consider all overloads of onFoo
in the base class, enabling regular lookup to find A::onFoo()
.
这篇关于C++ 虚函数被隐藏的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!