Effective C++ 总结[条款36 - 37]
条款36 【绝不重定义继承而来的non-virtual函数】
non-virtual函数是静态绑定(即声明变量时就确定了行为,不具有多态性),因此,重定义继承而来的non-virtual函数会覆盖掉基类中的同名函数。
class Player { public: Player() : _hp(100) {}; int GetHP() { return _hp; } public: int _hp; }; class Noele : public Player { public: Noele() : _shield(1000) { } int GetHP() { return _hp + _shield; } private: int _shield; }; int main() {
Noele wife; Player* p1 = &wife; p1->GetHP(); // Player::GetHP() Noele* p2 = &wife; p2->GetHP(); // Noele::GetHP()
return 0; }
条款37 【绝不重定义继承而来的缺省参数值】
静态类型,在程序中声明时所指定的类型,如示例代码中的p1的静态类型是Player*, p2的静态类型是Noele*, p3的静态类型是Player*;
动态类型,可在程序执行过程中改变(通常时赋值动作),如示例代码中的p3的动态类型是Noele*;
virtual函数是动态绑定来的,调用一个virtual函数时,究竟调用哪一份函数实现代码,取决于发出调用的那个对象的动态类型。
而缺省参数则取决于调用对象的静态类型,p3很好的诠释了这句话。
class Player { public: enum class Property { STONE = 0, FIRE, WATER, ICE, THUNDER, GRASS, WIND, }; virtual void CalcHP(Property pro = Property::FIRE) { std::cout << (int)pro << std::endl; } public: }; class Noele : public Player { public: virtual void CalcHP(Property pro = Property::STONE) { std::cout << (int)pro << std::endl; } private: }; int main() { Noele wife; Player* p1 = &wife; p1->CalcHP(); // 1-FIRE Noele* p2 = &wife; p2->CalcHP(); // 0-STONE
Player* p3 = new Noele;
p3->CalcHP(); // 1-FIRE, not 0-STONE
delete p3;
return 0; {
如果非要实现的话,只能考虑替代方案了。另缺省参数被non-virtual函数所指定,然后non-virtual函数内部调用virtual函数,这样继承类就不需要指定缺省参数值了。修改如下:
class Player { public: enum class Property { STONE = 0, FIRE, WATER, ICE, THUNDER, GRASS, WIND, }; void CalcHP(Property pro = Property::FIRE) { doCalcHP(pro); } virtual void doCalcHP(Property pro) { } public: }; class Noele : public Player { public: virtual void doCalcHP(Property pro) { } private: };

浙公网安备 33010602011771号