问题描述
我遇到了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)
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 );
};
此处使用
声明的效果是当查找 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 ++虚拟函数被隐藏的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!