2014-11-04 38 views
9

我對派生類中重新定義和重寫函數之間的區別感到困惑。在C++中重新定義與重寫

我知道 - 在C++中,重新定義的函數是靜態綁定的,重寫的函數是動態綁定的,並且重寫了虛擬函數,並重新定義了非虛函數。

當一個派生類「重新定義」了一個基類中的方法時,其被重新定義。但是當派生類是虛擬的時,它不再重新定義,而是重寫。所以我理解規則的後勤,但我不明白底線。

在下面的示例中,函數SetScore被重新定義。但是,如果我使基類虛擬的setScore函數(通過向其添加虛擬字),派生類中的setScore將被覆蓋。我不明白底線 - 有什麼區別。在setScore?

基類:

class GradedActivity 
{ 
protected: 
    char letter;   // To hold the letter grade 
    double score;   // To hold the numeric score 
    void determineGrade(); // Determines the letter grade 
public: 
    // Default constructor 
    GradedActivity() 
    { letter = ' '; score = 0.0; } 

// Mutator function 
    void setScore(double s) 
     { score = s; 
     determineGrade();} 

    // Accessor functions 
    double getScore() const 
     { return score; } 

     char getLetterGrade() const 
     { return letter; } 
}; 

派生類:

class CurvedActivity : public GradedActivity 
{ 
protected: 
    double rawScore;  // Unadjusted score 
    double percentage; // Curve percentage 
public: 
    // Default constructor 
    CurvedActivity() : GradedActivity() 
     { rawScore = 0.0; percentage = 0.0; } 

    // Mutator functions 
    void setScore(double s) 
     { rawScore = s; 
     GradedActivity::setScore(rawScore * percentage); } 

    void setPercentage(double c) 
     { percentage = c; } 

    // Accessor funtions 
    double getPercentage() const 
     { return percentage; } 

    double getRawScore() const 
     { return rawScore; } 
}; 

這是主要:

// Define a CurvedActivity object. 
    CurvedActivity exam; 

    ... 

    // Send the values to the exam object. 
    exam.setPercentage(percentage); 
    exam.setScore(numericScore); 
+0

覆蓋有助於類多態性。重載有利於函數多態性。重新定義既不會也是錯誤。 – orfdorf 2014-11-04 20:10:47

回答

14

這裏有一些基本的不同之處:

一種過載函數是一個函數,它與一個或多個其他函數共享其名稱,但具有不同的參數列表。編譯器根據所使用的參數選擇所需的函數。

安裝覆蓋函數是一個後代類中的方法,它具有與祖先類中的虛擬函數不同的定義。編譯器根據用於調用該函數的對象的類型來選擇所需的函數。

A 重新定義函數是一個後代類中的方法,它具有與祖先類中的非虛函數不同的定義。不要這樣做。由於該方法不是虛擬的,因此編譯器會根據對象引用的靜態類型而不是對象的實際類型來選擇調用哪個函數。

  • 靜態類型檢查意味着類型檢查發生在編譯時間。在這種情況下,在運行時不會使用類型信息。

  • 動態類型檢查在運行時使用類型信息時發生。 C++使用稱爲RTTI(運行時類型信息)的機制來實現這一點。使用RTTI的最常見的例子是dynamic_cast操作符,它允許向下廣播多態類型:

+0

謝謝,這可能是愚蠢的,但這是什麼意思:靜態類型的對象引用。 – YelizavetaYR 2014-11-04 20:10:26

+0

只有在相同範圍內,函數纔會重載。可能想補充一點。 – Deduplicator 2014-11-04 20:10:37

+3

*「編譯器根據用於調用函數的對象的類型來選擇所需的函數。」*這是不正確的,編譯器不會做出任何決定。這個決定是在運行時通過vtable查找完成的。 – Manu343726 2014-11-04 20:11:21