玩命加载中 . . .

37-绝不重新定义缺省参数


绝不重新定义继承而来的缺省参数值

派生类在重写虚函数的时候,如果修改了缺省参数,实际运行的时候使用的还是基类的虚函数的缺省参数

class Shape {
public:
    virtual void draw(int i = -1) const = 0;
};

class Rectangle : public Shape {
public:
    virtual void draw(int i = 1) const {
        cout << "Rectangle: " << i << endl;
    }
};

class Circle : public Shape {
public:
    virtual void draw(int i) const {
        cout << "Circle: " << i << endl;
    }
};

int main() {
    Shape *pr = new Rectangle;
    Shape *pc = new Circle;
    pr->draw(3);    // Rectangle: 3
    pc->draw(4);    // Circle: 4

    pr->draw(); // Rectangle: -1 使用基类的缺省值
    pc->draw(); // Circle: -1 使用基类的缺省值

    Circle x;
    x.draw();   // 静态绑定下,无法从base拿到默认值

    return 0;
}

虚函数是动态绑定的,而缺省参数值是静态绑定

为了保持派生类和基类有相同的缺省参数,可以给派生类提供跟基类一样的缺省参数

class Shape {
public:
    virtual void draw(int i = -1) const = 0;
};

class Rectangle : public Shape {
public:
    virtual void draw(int i = -1) const {
        cout << "Rectangle: " << i << endl;
    }
};

这样感觉比较重复,而且如果基类的缺省参数改变,所有派生也都得改

解决办法是将draw定义为非虚函数,然后调用一个私有的虚函数doDraw,并传递参数,派生类重写doDraw就行

class Shape {
public:
    void draw(int i = -1) const {
        doDraw(i);  // 调用虚函数,并传递参数
    }
private:
    virtual void doDraw(int i) const = 0;
};

class Rectangle : public Shape {
private:
    virtual void doDraw(int i) const {
        cout << "Rectangle: " << i << endl;
    }
};

class Circle : public Shape {
private:
    virtual void doDraw(int i) const {
        cout << "Circle: " << i << endl;
    }
};

int main() {
    Shape *pr = new Rectangle;
    Shape *pc = new Circle;
    pr->draw(3);    // Rectangle: 3
    pc->draw(4);    // Circle: 4

    pr->draw(); // Rectangle: -1
    pc->draw(); // Circle: -1

    Circle x;
    x.draw();   // Circle: -1 这样就可以使用基类的默认值

    return 0;
}

文章作者: kunpeng
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 kunpeng !
  目录