C++:虚函数(virtual function)缺省参数的异常表现及正确使用2014-11-16避免定义基类(base class)虚函数的缺省参数, 如果基类虚函数包含缺省参数, 派生类不要重新定义, 会产生异常;虚函数(virtual)是动态绑定(dynamically bound),缺省参数是静态绑定(statically bound).如果派生类(derived class)重新定义缺省值, 实例化, 执行函数正常;但在动态绑定时, 会出现,执行基类的缺省参数, 却是派生类的行为, 这样的异常举动.talk is cheap, show you the code.注意观察动态绑定时, pr的输出, 表现为基类的缺省参数, 派生类的动作.代码:
/** test.cpp**Created on: 2014.04.14*Author: Spike*//*eclipse cdt, gcc 4.8.1*/#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 {std::cout << "Rectangle : ";switch (color) {case Red :std::cout << "color = " << "Red" << std::endl;break;case Green :std::cout << "color = " << "Green" << std::endl;break;case Blue :std::cout << "color = " << "Blue" << std::endl;break;default:break;}}};class Circle : public Shape {public:virtual void draw(ShapeColor color) const {std::cout << "Circle : ";switch (color) {case Red :std::cout << "color = " << "Red" << std::endl;break;case Green :std::cout << "color = " << "Green" << std::endl;break;case Blue :std::cout << "color = " << "Blue" << std::endl;break;default:break;}}};int main() {Rectangle R;Circle C;R.draw();//C.draw(); //报错, 静态绑定无法继承参数Shape* pr = new Rectangle; //动态绑定Shape* pc = new Circle;pr->draw(Shape::Blue);pc->draw(Shape::Blue);pr->draw(); //静态绑定, 使用基类的默认参数, 完成派生类的动作pc->draw();return 0;}
输出:
Rectangle : color = GreenRectangle : color = BlueCircle : color = BlueRectangle : color = RedCircle : color = Red
如果想使用基类虚函数的缺省参数, 派生类不提供参数, 则需要使用NVI(non-virtual interface)的方法, 可以直接使用默认参数;但是, 绝对不要重新定义一个继承而来的缺省参数值.如, 以下代码中, Rectangle的私有虚函数, doDraw()不要提供默认参数.代码:
/** test.cpp**Created on: 2014.04.14*Author: Spike*//*eclipse cdt, gcc 4.8.1*/#include <iostream>#include <string>using namespace std;class Shape {public:enum ShapeColor {Red, Green, Blue};void draw(ShapeColor color = Red) const {doDraw(color);}private:virtual void doDraw(ShapeColor color) const = 0;};class Rectangle : public Shape {private:virtual void doDraw(ShapeColor color) const {std::cout << "Rectangle : ";switch (color) {case Red :std::cout << "color = " << "Red" << std::endl;break;case Green :std::cout << "color = " << "Green" << std::endl;break;case Blue :std::cout << "color = " << "Blue" << std::endl;break;default:break;}}};int main() {Rectangle R;R.draw();Shape* pr = new Rectangle; //动态绑定pr->draw(Shape::Blue);pr->draw();return 0;}
输出:
Rectangle : color = RedRectangle : color = BlueRectangle : color = Red
作者:csdn博客 Spike_King