C++ 为什么虚函数被隐藏?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4146499/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Why does a virtual function get hidden?
提问by Oszkar
I have the following classes:
我有以下课程:
class A {
public:
virtual void f() {}
};
class B : public A{
public:
void f(int x) {}
};
If I say
如果我说
B *b = new B();
b->f();
the compiler says error C2660: 'B::f' : function does not take 0 arguments. Shouldn't the function in B overload it, since it is a virtual function? Do virtual functions get hidden like this?
编译器说错误 C2660: 'B::f' : 函数不接受 0 个参数。B 中的函数不应该重载它,因为它是一个虚函数吗?虚函数会像这样隐藏吗?
EDIT: I indeed meant to inherit B from A, which shows the same behaviour.
编辑:我确实打算从 A 继承 B,这显示了相同的行为。
回答by Steve Jessop
Assuming you intended B
to derive from A
:
假设您打算B
从A
:
f(int)
and f()
are different signatures, hence different functions.
f(int)
和f()
是不同的签名,因此不同的功能。
You can overridea virtual function with a function that has a compatible signature, which means either an identical signature, or one in which the return type is "more specific" (this is covariance).
您可以使用具有兼容签名的函数覆盖虚函数,这意味着签名相同,或者返回类型“更具体”(这是协方差)。
Otherwise, your derived class function hides the virtual function, just like any other case where a derived class declares functions with the same name as base class functions. You can put using A::f;
in class B to unhide the name
否则,您的派生类函数会隐藏虚函数,就像派生类声明与基类函数同名的函数的任何其他情况一样。您可以放入using A::f;
class B 以取消隐藏名称
Alternatively you can call it as (static_cast<A*>(b))->f();
, or as b->A::f();
. The difference is that if B
actually does override f()
, then the former calls the override, whereas the latter calls the function in A
regardless.
或者,您可以将其称为(static_cast<A*>(b))->f();
或b->A::f();
。区别在于,如果B
确实进行了 override f()
,则前者调用了 override ,而后者则调用了 in 函数A
。
回答by Rod
Class B does not derive from A so no function F() exists. You probably meant:
B 类不是从 A 派生的,因此不存在函数 F()。你可能的意思是:
class A {
public:
virtual void f() {}
};
class B : public A {
public:
void f(int x) {}
};
Edit:I missed the actual function hiding. See Steve Jessop answer for more thorough explanation.
编辑:我错过了实际的功能隐藏。有关更详尽的解释,请参阅 Steve Jessop 的回答。
回答by Stuart Golodetz
No, and yes, respectively. If you want the overloading behaviour, you need to say
不,分别是。如果你想要重载行为,你需要说
using A::f;
in B.
在 B。
回答by bruziuz
It seems that it is exist rather similar question with answer in Biern Stroustrup's FAQ: http://www.stroustrup.com/bs_faq2.html#overloadderived
在 Biern Stroustrup 的常见问题解答中似乎存在相当相似的问题:http: //www.stroustrup.com/bs_faq2.html#overloadderived
As he said:
正如他所说:
"In C++, there is no overloading across scopes"
“在 C++ 中,跨作用域没有重载”
but if you want
但如果你愿意
"That's easily done using a using-declaration"
“使用 using 声明很容易做到这一点”
回答by Moo-Juice
B does not derive from A, the correct declaration is:
B 不是从 A 派生的,正确的声明是:
class B : public A
回答by Kelly S. French
When the compiler has more than one way to resolve a symbol, it has to choose which one has precedence unless the code tells it otherwise. What you are expecting is the overloading to take precedence over the overriding. (over, over, over, aaaaack! Sorry, got 'over'whelmed).
当编译器有不止一种方法来解析一个符号时,除非代码另有说明,否则它必须选择哪种方法具有优先权。您期望的是重载优先于覆盖。(结束,结束,结束,aaaaack!对不起,“不知所措”)。
This example has B inheriting a virtual method in which the subclass provides an overloaded version. Overloads are for methods in the same class using the same method name but different signatures. Since B is a subclass of A, it is overriding f(), which means it cannot also be an overload at the same time. This is why it is being hidden.
这个例子让 B 继承了一个虚方法,其中子类提供了一个重载版本。重载是针对同一类中使用相同方法名称但具有不同签名的方法。由于 B 是 A 的子类,它覆盖了 f(),这意味着它不能同时是一个重载。这就是它被隐藏的原因。
For class A, declaring method
对于A类,声明方法
virtual void f() {}
as virtual means that method will be resolved using a certain set of rules that are not consistent with your declaration of b.
as virtual 意味着该方法将使用一组与您的 b 声明不一致的规则来解析。
B *b = new B();
By creating 'b' as an instance of "B", the compiler has no need to use the virtual nature of the method of the same name in "A".
通过创建“b”作为“B”的实例,编译器不需要使用“A”中同名方法的虚拟性质。
If you had declared 'b' like this
如果你像这样声明了 'b'
B *b = new A();
then the call b->f(); would indeed refer to the method in A by making use of the virtual resolution.
然后调用 b->f(); 确实会通过使用虚拟分辨率来引用 A 中的方法。