【问题标题】:Why does a virtual function get hidden?为什么虚函数会被隐藏?
【发布时间】:2011-05-07 23:39:13
【问题描述】:

我有以下课程:

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


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

如果我说

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

编译器显示错误 C2660: 'B::f' : function does not take 0 arguments。 B中的函数不应该重载它,因为它是一个虚函数吗?虚函数会这样隐藏吗?

编辑:我确实打算从 A 继承 B,这显示了相同的行为。

【问题讨论】:

  • 也许你想从A派生B

标签: c++ virtual hide


【解决方案1】:

假设您打算将 B 派生自 A

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

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

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

您也可以将其称为(static_cast<A*>(b))->f();b->A::f();。不同的是,如果B确实覆盖了f(),那么前者调用了覆盖,而后者调用了A中的函数。

【讨论】:

  • 这就澄清了!我不知道为什么我认为使用virtual 时不应该发生隐藏。但我现在看到了。谢谢:)
  • 为什么我们不能隐藏不同返回类型的虚函数?即使是非虚函数也允许不同的返回类型。
  • @UnKnown:使用-virtual函数,函数是完全分离的; A * a = new B(); a.nonVirtualFunction() 将调用A::nonVirtualFunction,而不是B::nonVirtualFunction。但是对于virtual函数,它会调用B::nonVirtualFunction,所以很明显B::nonVirtualFunction必须至少与A::nonVirtualFunction兼容。
【解决方案2】:

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

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


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

编辑:我错过了隐藏的实际功能。有关更详尽的解释,请参阅 Steve Jessop 的回答。

【讨论】:

  • 虽然很好发现,但并不能解决问题(参见 Steve Jessops 的回答)。
  • LOL like @SteveJessop 我跳过了签名问题,甚至没有注意到B 不是源自A! +1
  • @wilhelmtell:正确,直到 Rod 指出,我才注意到丢失的继承。
  • 确实,我忘了这样写,但史蒂夫杰索普的回答澄清了正确的情况。
【解决方案3】:

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

using A::f;

在 B.

【讨论】:

  • 确实,我错过了 :) 不过,如果是这样的话,这就是你需要做的。
  • 是的,我的意思是派生它。谢谢!
【解决方案4】:

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

class B : public A

【讨论】:

    【解决方案5】:

    当编译器有多种方法来解析符号时,它必须选择哪一种具有优先权,除非代码另有说明。您所期望的是重载优先于覆盖。 (结束了,结束了,结束了,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->f();确实会通过使用虚拟分辨率来引用A中的方法。

    【讨论】:

      【解决方案6】:

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

      正如他所说:

      “在 C++ 中,没有跨范围的重载”

      如果你愿意的话

      “使用 using 声明很容易做到这一点”

      【讨论】:

        猜你喜欢
        • 2011-10-07
        • 2013-11-13
        • 1970-01-01
        • 1970-01-01
        • 2011-11-30
        • 1970-01-01
        • 2018-06-06
        • 2019-09-28
        • 1970-01-01
        相关资源
        最近更新 更多