首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> 關於C++

C++ 虛擬函式預設參數陷阱與正確用法

     編輯:關於C++

核心問題

虛擬函式為動態綁定(執行期決定),預設參數為靜態綁定(編譯期決定)。若基類別虛擬函式有預設參數,派生類別覆寫時不要重新定義預設參數,否則會出現「基類別預設參數配合派生類別函式本體」的異常行為。

程式碼示範

/* test.cpp
 * Created on: 2014.04.14
 * Author: Spike
 */
#include <iostream>
#include <string>
using namespace std;

class Shape {
public:
    enum ShapeColor { Red, Green, Blue };
    virtual void draw(ShapeColor color = Red) const = 0;
};

class Rectangle : public Shape {
public:
    virtual void draw(ShapeColor color = Green) const { // 錯誤:重新定義預設參數
        cout << "Rectangle : ";
        switch (color) {
            case Red:   cout << "Red"; break;
            case Green: cout << "Green"; break;
            case Blue:  cout << "Blue"; break;
        }
        cout << endl;
    }
};

class Circle : public Shape {
public:
    virtual void draw(ShapeColor color) const { // 正確:不提供預設參數
        cout << "Circle : ";
        switch (color) {
            case Red:   cout << "Red"; break;
            case Green: cout << "Green"; break;
            case Blue:  cout << "Blue"; break;
        }
        cout << endl;
    }
};

int main() {
    Rectangle R; Circle C;
    R.draw();           // 靜態綁定:Green
    Shape* pr = new Rectangle;
    Shape* pc = new Circle;
    pr->draw(Shape::Blue); // 動態綁定:Blue
    pc->draw(Shape::Blue); // 動態綁定:Blue
    pr->draw();           // 危險!靜態綁定用基類別預設 Red,動態綁定執行 Rectangle::draw(Red)
    pc->draw();           // 正常:Circle 無預設參數,編譯錯誤(需傳參數)
    return 0;
}

輸出(pr->draw() 那行)

Rectangle : Red   // 基類別預設參數 Red,但執行 Rectangle 版本

規則總結

  1. 基類別虛擬函式可有預設參數。
  2. 派生類別覆寫時不可重新定義預設參數。
  3. 透過基類別指標/參考呼叫時,使用靜態型別的預設參數,動態型別的函式本體。
  4. 最佳實務:虛擬函式不要使用預設參數,或在所有層級保持一致(但語言不強制)。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved