为什么隐藏虚拟功能?

时间:2010-11-10 16:14:59

标签: c++ virtual hide

我有以下课程:

class A {
public:
    virtual void f() {}
};


class B : public A{
public:
    void f(int x) {}
};

如果我说

B *b = new B();
b->f();

编译器说错误C2660:'B :: f':函数不带0个参数。 不应该B中的函数超载它,因为它是一个虚函数?虚拟函数会像这样被隐藏吗?

编辑:我的意思是从A继承B,这显示了相同的行为。

6 个答案:

答案 0 :(得分:36)

假设您打算B派生自A

f(int)f()是不同的签名,因此功能不同。

您可以使用具有兼容签名的函数覆盖虚拟函数,这意味着相同的签名,或者返回类型为“更具体”的签名(这是协方差)。

否则,派生类函数会隐藏虚函数,就像派生类声明与基类函数同名的函数一样。您可以将using A::f;放在B类中取消隐藏名称

或者,您可以将其称为(static_cast<A*>(b))->f();b->A::f();。不同之处在于,如果B实际上覆盖了f(),那么前者会调用覆盖,而后者会调用A中的函数。

答案 1 :(得分:7)

B类不是从A派生的,因此不存在函数F()。你可能意味着:

class A {
public:
    virtual void f() {}
};


class B : public A {
public:
    void f(int x) {}
};

编辑:我错过了隐藏的实际功能。请参阅Steve Jessop的答案以获得更详尽的解释。

答案 2 :(得分:4)

不,是的,分别。如果您想要重载行为,则需要说

using A::f;

在B。

答案 3 :(得分:2)

B不是从A派生的,正确的声明是:

class B : public A

答案 4 :(得分:2)

当编译器有多种方法来解析符号时,它必须选择哪一个具有优先权,除非代码另有说明。您期望的是超载优先于覆盖。 (over,over,over,aaaaack!对不起,得到了'过来'。)

此示例使B继承了一个虚方法,其中子类提供了重载版本。重载是针对同一类中使用相同方法名但具有不同签名的方法。由于B是A的子类,它重写了f(),这意味着它不能同时成为一个重载。这就是它被隐藏的原因。

对于A类,声明方法

virtual void f() {}  

as virtual意味着将使用与您的b声明不一致的某组规则来解析方法。

B *b = new B();

通过创建“b”作为“B”的实例,编译器无需使用“A”中同名方法的虚拟特性。

如果你已经像这样声明了'b'

B *b = new A();  

然后调用b-&gt; f();确实会通过使用虚拟分辨率来引用A中的方法。

答案 5 :(得分:2)

在Biern Stroustrup的常见问题解答中,它似乎与答案存在相似的问题:http://www.stroustrup.com/bs_faq2.html#overloadderived

正如他所说:

  

“在C ++中,范围内没有超载”

但如果你想要

  

“使用using声明很容易完成”