簡體   English   中英

關於C ++虛擬函數的一個問題

[英]one question about C++ virtual function

我的朋友問我一個虛函數問題。

如果子對象調用虛擬函數,那么在什么條件下,該虛擬函數實際上是在父親的實現中執行的?

我認為您需要發布一些代碼來澄清您的要求,但是(析構函數除外)除非子級從其自己的函數中顯式調用它,否則不會調用基類函數。 例如,在:

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()。

無法理解當前形式的問題到底暗示了什么。

如果從字面上看,這個問題有一個明顯而直接的答案:如果父代的實現是相關函數的最終替代者,即子代未提供其自身的實現,則調用父代的版本。

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 */ }
};

但是,為此問題的措詞不正確。 在調用時的最后一個示例中,子對象尚不存在。 它的內存已分配,但其生命期尚未開始。 說虛函數的調用是由子對象執行的,這是不正確的。 它由父對象執行。

因此,請繼續以上內容:這個問題的措詞含糊不清,以目前的形式沒有任何意義。

  • 當顯式使用基類的范圍時( Base::f();
  • 在基類的構造函數內部(因為尚未輸入派生對象的構造函數)
  • 在基類的析構函數內部(因為派生對象已被破壞)

如果已經調用了子類的析構函數,則該對象現在是父類的類型,因此將調用父類的虛函數。

如果此調用在構造函數中進行,則調度將是靜態的。 請閱讀以下詳細信息: 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的對象調用。

已經提供了答案,這可能在構造過程中發生:

它也可能是運行時錯誤的有趣來源,因此請特別注意基類中的構造函數和純虛方法調用;)

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()
   {
   }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM