2016-02-02 89 views
-2

關於下面的代碼:關於虛函數和繼承

class A { 
    A * next; 
    static A* tmp; 
public: 
    A() : next(tmp) { 
     if (tmp) 
      tmp->next = this; 
     tmp = this; 

    } 
    virtual void print() { 
     if (next) 
      next->print(); 
    } 
}; 
class B : public A { 
    int a = 1; 
public: 
    void print() { 
     cout << "foo"; 
     A::print(); 
    } 
}; 
A* A::tmp; 
int main(){ 
    B c; 
    B b; 
    b.print(); 
} 

爲什麼next->print();導致B::print()並沒有恢復到A::print()?由於next是一個靜態指針A爲什麼它會去B的函數?

編輯:添加B c;,我發佈時意外刪除。

+0

這很奇怪,在VS15它確實進入下一個... @NathanOliver – shinzou

+0

我刪除了一行,當我發佈這個,它現在不是空。 @NathanOliver – shinzou

+0

@NathanOliver它現在做:https://ideone.com/qnrfUb – shinzou

回答

1

由於下一個是甲

next靜態指針不是靜態指針。即使你可能已經從靜態存儲指針複製初始化它。但是否是靜態的,與成員函數調用的工作方式無關。

爲什麼它去B的功能?

因爲print是虛擬功能。如果指針A* next指向B的實例,則next->print()將調用B::print()。這被稱爲虛擬或動態調度。

如果你想叫A::print()代替,那麼你也可以使用靜態調度:

next->A::print(); 

當然,如果您只想使用靜態調度,那麼就沒有任何意義申報該功能首先是虛擬的。

+0

它現在。 OP做了一個完整的例子。我刪除了我的評論。 – NathanOliver

+0

但在我的其他問題在這裏:http://stackoverflow.com/a/35095397/4279201我被告知名稱查找是基於靜態類型,所以在這種情況下,不應該'A'的指針尋找一個'A'的函數,不管它指向什麼類型? – shinzou

+0

@kuhaku名稱查詢和虛擬調度是兩個分開的事情。 'print'這個名字只能從'A'類型中查找,但是因爲它恰好是一個虛函數,所以這個調用將被虛擬地調度。 – user2079303

2

在您的代碼中,next->print();根本不會被調用。如果你可以調試它,你會發現next在這裏是null。

LIVE

編輯

與您編輯的代碼,該過程將是infinate。 next->print();將導致B::print(),即使next的靜態類型爲A*,但A::print()是一個虛擬函數,並且next事實上指向B的實例,因此動態多態性在此處起作用。

+0

@kuhaku'B :: print()'確實會被調用一次。我試過了[這裏](http://rextester.com/JQUHE78947)。 – songyuanyao

+0

我在發佈這條消息時意外刪除了一條重要線路...... – shinzou