关于C ++虚函数的一个问题

时间:2009-12-12 20:07:43

标签: c++

我的朋友问我虚拟功能问题。

如果一个子对象调用一个虚函数,在什么条件下,这个虚函数实际上是在父实现中执行的?

6 个答案:

答案 0 :(得分:3)

我认为你需要发布一些代码来澄清你的要求,但是(除了析构函数)基类函数不会被调用,除非子函数从它自己的函数中显式调用itt。例如,在:

struct A {
    virtual ~A() {}
    virtual void f() {}
};

struct B : public A {
    virtual void f() {}
};

int main() {
    A * a = new B;
    a->f();
    delete a;
}

只调用B的虚函数f()。如果你想要调用A :: f(),你必须明确地这样做:

struct B : public A {
    virtual f() { 
       A::f();    // explicit call
    }
};

哦,当然在B没有声明函数的情况下 - 在这种情况下,将始终调用A :: f()。

答案 1 :(得分:2)

无法理解当前形式的问题究竟隐含的内容。

如果按字面意思理解,问题有一个明显而直接的答案:如果父母的实现是相关函数的最终覆盖,即如果孩子没有提供自己的实现,则调用父版本

class parent {
public:
  virtual void foo() { /* whatever */ }
};

class child : parent {
public:
  void bar() {
    foo(); /* call the parent's implementation, as requested */
  }
};

所以,这是你的答案。

当然,对于任何最有可能不是这个问题所隐含的内容的人来说,这是直观明显的。很可能暗示子类覆盖了父类的功能。在这种情况下,还有另一个明显的答案:如果孩子使用函数的完全限定名称,将调用父版本

class parent {
public:
  virtual void foo() { /* whatever */ }
};

class child : parent {
public:
  virtual void foo() { /* whatever */ }
  void bar() {
    parent::foo(); /* call the parent's implementation, as requested */
  }
};

另一个可能的答案是,调用该函数的对象实际上具有parent类型(因为它在问题中没有说明孩子应该为this对象调用它)

class parent {
public:
  virtual void foo() { /* whatever */ }
};

class child : parent {
public:
  virtual void foo() { /* whatever */ }
  void bar() {
    parent p;
    p.foo(); /* call the parent's implementation, as requested */
  }
};

同样,直觉上感觉这不是问题所在。最有可能的问题是关于构造函数和析构函数的虚拟调用

class parent {
public:
  parent() { 
    foo(); /* always calls `parent::foo` */
  }
  virtual void foo() { /* whatever */ }
};

class child : parent {
public:
  child() : parent() /* `parent::parent` will call `parent::foo` */
    {}
  virtual void foo() { /* whatever */ }
};

然而,问题的措辞不正确。在调用时的最后一个示例中,子对象尚不存在。它的内存已经分配但其生命周期尚未开始。说对虚拟函数的调用是由子对象执行的,这是不正确的。它由父对象执行。

所以,要恢复上述内容:这个问题含糊不清,措辞模糊,以现在的形式没有任何意义。

答案 2 :(得分:1)

  • 明确使用基类的范围时(Base::f();
  • 在基类的构造函数内部(因为尚未输入派生对象的构造函数)
  • 在基类的析构函数内部(因为派生对象已经被破坏)

答案 3 :(得分:0)

如果已经调用了子类的析构函数,那么该对象现在是父类型,因此将调用父类的虚函数。

答案 4 :(得分:0)

如果此调用在构造函数中,则调度将是静态的。阅读本文以获取更多信息:http://cplusplus.co.il/2009/09/30/virtual-dispatching-within-a-constructor-or-a-destructor/

以下是我链接到的文章中的示例:

struct A {
    A () { f(); }
    virtual void f () { }
};

struct B : A {
        B () :member(0) {}
        void f () { std::cout << member; }
    private:
        int member;
};

int main () {
    B b;
    return 0;
}

调用的f是A :: f,尽管它是虚拟的并且由具有自己实现的类型B的对象调用。

答案 5 :(得分:0)

已经提供了答案,这可能在施工期间发生:

它可能也是运行时错误的一个有趣来源,所以要特别注意构造函数&amp;基类中的纯虚方法调用;)

http://support.microsoft.com/kb/125749

   class A;

   void fcn( A* );

   class A
   {
   public:
       virtual void f() = 0;
       A() { fcn( this ); }
   };

   class B : A
   {
       void f() { }
   };

   void fcn( A* p )
   {
       p->f();
   }

   // The declaration below invokes class B's constructor, which
   // first calls class A's constructor, which calls fcn. Then
   // fcn calls A::f, which is a pure virtual function, and
   // this causes the run-time error. B has not been constructed
   // at this point, so the B::f cannot be called. You would not
   // want it to be called because it could depend on something
   // in B that has not been initialized yet.

   B b;

   void main()
   {
   }