2016-03-13 32 views
3

我已經在cpp中編寫代碼來測試我對動態調度的理解。我認爲在我的程序中輸出應該是「我在NT」。我的理由是:動態調度OOP

  1. tMethod被定義爲虛擬的,所以動態綁定將用於
  2. 在運行時類類型的test是NT,所以打電話test->tMethod(ont)應該尋找裏面NT
  3. 實施
  4. 實際參數ont的類型是NT的,所以找到精確匹配是tMethod
  5. 的NT的impementation

不過,這一方案的輸出爲「我T中我」。

我的推理出了什麼問題?

#include <iostream> 

    using namespace std; 

    class T { 

     public: 
      virtual void tMethod(T){ 
       cout<<"I'm in T"<<endl; 
      } 

    }; 

    class NT: public T{ 
     public: 
      void tMethod(NT){ 
       cout<<"I'm in NT"<<endl; 
      } 

    }; 


    int main() 
    { 
     NT ont; 

     T* test=new NT(); 

     test->tMethod(ont); 

     return 0; 
    } 
+1

'NT :: tMethod()'採用不同的參數類型到'N :: tMethod()',所以它不會覆蓋。使用'override'關鍵字來防止這種情況 – Galik

+0

儘管如此,也許在這個例子中,他不能使用任何多態的能力,並且可能會遇到未定義的行爲,因爲他通過價值傳遞了它。例如,切片。 – Incomputable

+1

@OlzhasZhumabek這不會是未定義的行爲,除非這些類在其實現中存在UB錯誤。 – juanchopanza

回答

5

這種方法:

void tMethod(NT){ 

不會覆蓋這一個:從NT

virtual void tMethod(T){ 

您已經更改參數類型T

您可以添加覆蓋關閉這個將其誤入錯誤:

void tMethod(NT) override { 

將輸出:

main.cpp:16:18: error: 'void NT::tMethod(NT)' marked 'override', but does not override void tMethod(NT) override {

[編輯]

你的實際問題是爲什麼C++不允許重載跨類的傳承的功能,具體地,涉及能夠訪問使用鹼衍生類函數類指針。原因是語言不支持此功能。您可以在Bjarne Stroustrup常見問題解答中找到類似的問題:Why doesn't overloading work for derived classes?

+0

爲什麼它需要覆蓋它?我同意這不是重新定義(我認爲這是超載)。但NT類仍然有兩種方法,一種是繼承的,另一種是NT類型的新方法。現在在我的情況下,當查找適當的函數時,爲什麼當實際參數是NT類型時,選擇了類型T的形式參數的函數? – balboa

+0

'test-> tMethod(ont);'在類類型T的指針上進行函數調用,這意味着只會調用T中的方法。將'T * test'改爲'NT * test'並且'void tMethod(NT)'將被調用。 – marcinj

+0

它是類類型T的指針,但在運行時它指向類類型NT。不應該在NT內搜索方法嗎?我認爲這是多態的主要思想。 – balboa

2

NT::tMethod()採用不同的參數類型爲N::tMethod(),因此它不會覆蓋。使用override關鍵字,以防止這一點:

#include <iostream> 

using namespace std; 

class T 
{ 

public: 
    virtual void tMethod(T) { 
     cout << "I'm in T" << endl; 
    } 
}; 

class NT: public T 
{ 
public: 
    void tMethod(NT) override { // use override keyword here 
     cout << "I'm in NT" << endl; 
    } 
}; 

int main() 
{ 
    NT ont; 

    T* test = new NT(); 

    test->tMethod(ont); 

    return 0; 
} 

現在你應該得到一個編譯錯誤,因爲你標記MT::tMethod()override但由於它採用了不同的參數類型沒有。

1

你最好使用指針或引用基類作爲虛方法中的一個參數。如果您需要在overriden方法中使用派生類,那麼您可以使用dynamic_cast。

class T { 

    public: 
     virtual void tMethod(T*){ 
      cout<<"I'm in T"<<endl; 
     } 

}; 

class NT: public T{ 
    public: 
     virtual void tMethod(T* t) override { 
      NT* nt=dynamic_cast<NT*>(t); 
      if (nt) 
      { 
       cout<<"I'm in NT as NT"<<endl; 
      } 
     }  
}; 


int main() 
{ 
    NT ont; 

    T* test=new NT(); 

    test->tMethod(&ont); 

    return 0; 
}