【问题标题】:C++ Inherited Virtual Method Still Uses Base Class ImplementationC++ 继承的虚方法仍然使用基类实现
【发布时间】:2010-01-21 20:46:30
【问题描述】:

我有一个名为 Packet 的基类:

// Header File
class Packet {
public:
    virtual bool isAwesome() const {
        return false;
    }
}

还有一个名为AwesomePacket的继承类:

// Header File
class AwesomePacket : public Packet {
public:
    virtual bool isAwesome() const {
        return true;
    }
}

但是,当我实例化一个AwesomePacket 并调用isAwesome() 时,该方法返回false 而不是true。为什么会这样?

【问题讨论】:

  • 能否包含实例化它的代码并调用该方法?
  • 更准确地说:您能否提供一个真实完整的示例,即开箱即用的编译示例。请告诉我们您正在使用哪个编译器,哪些编译器选项处于活动状态等。
  • 您不需要为后代(子)类中的方法添加前缀virtual
  • Thomas,你是对的,但我发现用 virtual 标记子类中覆盖的方法非常有用 - 很明显这是故意的。

标签: c++ inheritance virtual


【解决方案1】:

您的代码很可能在 Packet 构造函数中调用 isAwesome:

Packet::Packet()
{
    // this will always call Packet::isAwesome
    if (isAwesome())
    {
    } 
}

即使这个 Packet 构造函数被用来构造 AwesomePacket 对象的父对象,它也不会调用 AwesomePacket::isAwesome。这是因为此时该对象还不是 AwesomePacket。

【讨论】:

    【解决方案2】:

    这完全取决于您如何调用该方法。考虑一下:

    AwesomePacket ap;
    bool awesomeness0( ap.isAwesome()); // true, call is direct, not through vtable
    
    AwesomePacket& rap( ap );
    bool awesomeness1( rap.isAwesome()); // true, call is direct, not through vtable
    
    Packet p( ap ); // WRONG (but legal): slicing child instance into space of parent
    bool awesomeness2( p.isAwesome()); // false, call is direct, not through vtable
    
    const Packet& rp( ap ); // the right way
    bool awesomeness3( rp.isAwesome()); // true, call is through vtable
    
    const Packet* pp( &ap ); // also the right way
    bool awesomeness4( pp->isAwesome()); // true, call is through vtable
    

    这就是说 C++ 中的多态性只能通过引用或指向基址的指针起作用。

    编辑:

    不要忘记在基类中添加一个虚拟析构函数

    编辑:

    这还取决于您调用虚拟方法的位置,请参阅 R Samuel Klatchko 的答案。

    【讨论】:

    • 如果我没记错的话,你的最后一个例子应该是pp->isAwesome()
    • 第二个例子(awesomeness1)的评论不正确。由于rap 是一个引用,调用通过vtable,而不是直接的。但返回true 是正确的。
    • 只有 Java 程序员才会犯的错误,按值传递对象。
    • 乔恩-埃里克,你说得对。编译器已经知道确切的对象类型,因此它不需要通过 vtable,并且可能只生成直接调用而不是虚拟调用。
    猜你喜欢
    • 2012-12-12
    • 2018-12-07
    • 2016-10-08
    • 1970-01-01
    • 2016-07-12
    • 1970-01-01
    • 1970-01-01
    • 2012-04-22
    • 2013-09-11
    相关资源
    最近更新 更多