- 通过virtual继承实现接口:比如下面的Hero类的healthValue类,但有一些缺点:派生类不想实现的方法必须实现。又或者继承了不想用的特殊方法,于是本文围绕virtual函数的替代方法写了三种办法
#include <iostream>
class GameCharacter {
public:
virtual int healthValue()const {
std::cout << "Base" << std::endl;
return 0;
};
};
class Hero : public GameCharacter{
public:
virtual int healthValue()const {
std::cout << "Derived" << std::endl;
return 0;
};
};
int main() {
Hero mhero;
mhero.healthValue();
return 0;
}
- (1)替代方案之用NVI(non virtual interface)
#include <iostream> class GameCharacter { private: virtual int dohealthValue()const { std::cout << "Base" << std::endl; return 0; }; }; class Hero : public GameCharacter{ public: int healthValue() const //客户调用public接口,实现对具体实现动作dohealthValue()封装 { // 可以实现其他动作 return dohealthValue(); }; private: virtual int dohealthValue()const { std::cout << "Derived" << std::endl; return 0; }; }; int main() { Hero mhero; mhero.healthValue(); return 0; }
在Hero类把继承来的virtual函数的接口进行封装,并且对外提供封装,这种操作叫做NVI,但这其实也没有完全的避开重写virtual函数,这是相比把所有的动作放到dohealthValue(); 多了一层封装,但比完全的继承要好一些。
- (2)通过函数指针来执行需要的动作,从而避免virutal的继承。
#include <iostream> class GameCharacter; int defHealthCalcFunc(const GameCharacter &) { std::cout << "defHealthCalcFunc" << std::endl; return 0; } class GameCharacter { public: typedef int (*HealthCalcFunc) (const GameCharacter&); explicit GameCharacter(HealthCalcFunc hcf = defHealthCalcFunc): healthFunc(hcf) { }; int dohealthValue() const { std::cout << "Base" << std::endl; return healthFunc(*this); //调用defHealthCalcFunc() }; private: HealthCalcFunc healthFunc; }; int main() { GameCharacter mhero; //默认构造,传入defHealthCalcFunc函数 mhero.dohealthValue(); return 0; }
通过传入函数指针似乎可以解决一些问题,但传入的函数指针函数,你没办法再函数里面用这个class的private部分参数/函数。解决办法是放弃private属性,或者再public内添加接口供函数指针函数使用。但似乎也带来了额外的开销,具体需要看情况抉择。
- 用std::function替代------略(理解不清楚)
- (3)古典策略模式
#include <iostream> #include <functional> class GameCharacter; // int defHealthCalcFunc(const GameCharacter &) { // std::cout << "defHealthCalcFunc" << std::endl; // return 0; // } class HealthCalcFuncBase { //Base public: virtual int calc(const GameCharacter& gc)const { return 0; }; }; class HealthCalcFuncDerived : public HealthCalcFuncBase{ // Derived public: HealthCalcFuncDerived() { std::cout << "HealthCalcFuncDerived start" << std::endl; } ~HealthCalcFuncDerived() { std::cout << "HealthCalcFuncDerived finish" << std::endl; } virtual int calc(const GameCharacter& gc)const { std::cout << "HealthCalcFuncDerived" << std::endl; return 0; } }; HealthCalcFuncBase defaultHealthCalc; class GameCharacter { public: explicit GameCharacter(HealthCalcFuncBase* hcf = &defaultHealthCalc) :pHealthCalc(hcf) {} int healthValue() { return pHealthCalc->calc(*this); } private: HealthCalcFuncBase* pHealthCalc; }; int main() { HealthCalcFuncDerived tmp; GameCharacter mhero(&tmp); mhero.healthValue(); return 0; }
通过HealthCalcFuncDerived继承实现HealthCalcFuncBase,然后再构造GameCharacter()传入HealthCalcFuncDerived tmp;对象,通过多态实现调用HealthCalcFuncDerived的方法,避免了GameCharacter的继承。。。