【问题标题】:Have I implemented a pure virtual function wrong?我是否实现了一个纯虚函数错误?
【发布时间】:2012-03-21 00:17:02
【问题描述】:

编辑:

我没有更新问题,在这样做的同时我意识到问题的范围已经完全改变,所以我对此表示歉意。我正在处理线程,因此必须存在静态函数。我试图尽可能地从问题中抽象出 Threading 的东西。

我收到pure virtual function call 错误,所以我想我的实现可能有误。这是我所拥有的:

class Base
{
    protected:
        virtual int f(void) = 0;
        static void baseFunction(void* param);
};

static void Base::baseFunction (void* param)
{
    Base *parent = (Base*) parameter;

    int i = parent->f();
}

class Derived : public Base
{
    private:
        int _memeber;
        int f(void);
};

int Derived::f(void)
{
    _member = 0;

    cout << "Derived _memeber is: " << _member << endl;

    return 0;
}

void main ()
{
    Derived d;

    d.baseFunction(d);
}

我需要函数Derived::f(void) 才能访问Derived 类成员。

【问题讨论】:

  • 这是实际代码吗?任何一个类的定义后面都没有分号。
  • 另外,定义应该是int Derived::f(void)。但是你什么时候得到错误?它是编译器还是运行时错误?你确定你打电话给Derived吗?
  • 代码原样(以 hmjd 的注释为模)很好。应该还有什么问题。
  • 您在哪里使用Derived 对象?您是否将其按值传递给期望Base 的函数?如果是这样,它将被切片,并且虚拟函数在运行时将不存在。
  • @PeterWood:不能切片——纯虚函数会阻止基类的实例化。

标签: c++ oop polymorphism virtual


【解决方案1】:

定义看起来不错,但我会冒险猜测您是从Base 的构造函数或析构函数调用虚函数。在这种情况下,虚拟分派就像动态类型是Base,而不是Derived,并且如果函数是纯虚拟的,那么你会得到未定义的行为。

更新:您还说“我正在处理线程”。在这种情况下,数据竞争可能会导致一个线程调用该函数,而另一个线程仍在构造对象 - 再次给出未定义的行为。您需要确保所有数据访问都正确同步。

【讨论】:

  • +1:VC10检测到这个并报告为“未解决”,VC9抛出“纯虚函数调用”错误
  • 有趣的是,我从 Derived 类的构造函数中删除了参数,一旦将它们添加回来,我就不再遇到任何问题了。所以这样做:Derived d; 有效,但这样做:Derived d = Derived(param) 无效。
【解决方案2】:

没关系,只是类声明后面少了分号。

【讨论】:

    【解决方案3】:

    为 Derived 方法添加返回类型。类定义后还要加分号

    【讨论】:

      【解决方案4】:

      您缺少 f 和 ; 的返回类型在类定义之后

      将您的代码更改为

      class Base
      {
          protected:
              virtual int f(void) = 0;
      };
      
      class Derived : public Base
      {
          public:
              int f(void);
      };
      
      int Derived::f(void)
      {
          // do something here
      }
      

      此外,如果可能,请发布可运行的代码。我添加了

      int main()
      {
          Derived d;
          d.f();
      }
      

      到您的代码示例

      【讨论】:

        【解决方案5】:

        公开两个类中的所有函数。你为什么要声明 int i?根本没用过。

        【讨论】:

          【解决方案6】:

          你需要声明

          class Derived : public Base
          {
              protected:
                  virtual int f(void);
          }
          

          我想你的纯虚函数调用来自基类,在它的另一个方法中使用 f。

          【讨论】:

          • 或者从基类构造函数调用f
          • 不,在基类中声明方法virtual 使其在所有派生类中都是虚拟的。您不需要在孩子中指定virtual
          猜你喜欢
          • 2016-03-07
          • 2016-01-16
          • 2016-02-18
          • 1970-01-01
          • 1970-01-01
          • 2021-10-26
          • 2013-12-31
          相关资源
          最近更新 更多