在Effective C ++,3rd Edition,Page 173~175中,Scott Meyers使用策略模式讨论了虚拟功能的替代方案:
class GameCharacter;
int defaultHealthCalc(const GameCharacter& gc);
class GameCharacter {
public:
typedef std::tr1::function<int (const GameCharacter&)> HealthCalcFunc;
explicit GameCharacter(HealthCalcFUnc hcf = defaultHealthCalc)
: healthFunc(hcf)
{}
int healthValue const
{ return healthFunc(*this) }
...
private:
HealthCalcFunc healthFunc;
};
...
struct HealthCalculator {
int operator()(const GameCharacter&) const
{ ... }
};
...
class EyeCandyCharacter: public GameCharacter {
explicit EyeCandyCharacter(HealthCalcFunc hcf=defaultHealthCalc)
:GameCharacter(hcf)
{ ... }
...
}
...
EyeCcandyCharacter ecc(HealthCalculator());
最后一个语句是说明如何在EyeCandyCharacter
类的构造函数中使用运行状况计算函数对象。
我的问题是,EyeCandyCharacter
类的构造函数需要一些函数,该函数使参数与const GameCharacter&
兼容并返回可转换为int
的内容。
这是由operator()
中定义的struct HealthCalculator
支持/实施的吗?我不太明白这个重载运算符的含义。
我的另一个问题是,派生类的构造函数中的初始化列表通常只初始化自身的数据成员(虽然我知道派生类的基本部分也是隐式初始化的)。为什么基类GameCharacter
出现在派生类EyeCandyCharacter
的初始值设定项中?
答案 0 :(得分:2)
在你的第一个问题中:
我的问题是,EyeCandyCharacter类的构造函数需要 一些带有与const兼容的参数的函数 GameCharacter&安培;并返回可转换为int的内容。 ......是的 这由struct()中定义的operator()支持/实现 HealthCalculator?
是的,它受到支持。您必须知道/记住HealthCalculator
是functor。它实现了operator ()
来“模拟”调用传统函数的语法。其operator ()
需要const GameCharacter&
并返回int
,该EyeCandyCharacter
与GameCharacter
(以及随后的EyeCandyCharacter
)想要的内容兼容。
在你的第二个问题中:
基类GameCharacter如何出现在初始化器中 派生类EyeCandyCharacter?
通过调用GameCharacter
的构造函数初始化GameCharacter
的基类EyeCandyCharacter
。不执行此操作会导致GameCharacter
的构造函数调用std::function
的默认构造函数(未定义),因此会导致错误。
作为旁注,您现在可以在C ++ 11中直接使用std::tr1::function
,其功能与{{1}}大致相同。
答案 1 :(得分:1)
关于你的第二个问题:
我的另一个问题是,派生类的构造函数中的初始化列表通常只初始化自身的数据成员(虽然我知道派生类的基本部分也是隐式初始化的)。 为什么基类GameCharacter出现在派生类EyeCandyCharacter的初始值设定项中?
不,如果您的基类没有定义default constructor
,但是定义了其他构造函数,则必须调用基于类的构造函数来初始化基类成员。因为在这种情况下,编译不会为您生成default constructor
。换句话说,
派生类的基础部分 NOT 始终隐式初始化