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:
    
};

 

posted @ 2022-05-06 21:35  straymonkey  阅读(45)  评论(0)    收藏  举报