Reputation: 4803
In Effective C++, 3rd Edition, Page 173~175, Scott Meyers talked of alternatives to virtual functions using the strategy pattern:
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());
The last statement is to illustrate how to use a health calculation function object in the constructor of EyeCandyCharacter
class.
My question is, the constructor of EyeCandyCharacter
class requires some function that takes a parameter compatible with a const GameCharacter&
and returns something convertible to an int
.
Is this supported/implemented by operator()
defined in struct HealthCalculator
? I don't quite understand the meaning of this overloaded operator here.
Another question of mine here is that the initializer list in the constructor of the derived class usually only initializes the data members of itself (though I know the base part of the derived class is also intialized implicitly). How come the base class GameCharacter
appears in the initializer of derived class EyeCandyCharacter
?
Upvotes: 0
Views: 188
Reputation: 17708
In your first question:
My question is, the constructor of EyeCandyCharacter class requires some function that takes a parameter compatible with a const GameCharacter& and returns something convertible to an int. ... Is this supported/implemented by operator() defined in struct HealthCalculator?
Yes, it is supported. You must know/remember that HealthCalculator
is a functor. It implements the operator ()
to "simulate" the syntax of calling traditional functions. Its operator ()
takes a const GameCharacter&
and returns an int
, which is compatible with what EyeCandyCharacter
(and subsequently GameCharacter
) wants.
In your second question:
How come the base class GameCharacter appears in the initializer of derived class EyeCandyCharacter?
That initializes the base class of EyeCandyCharacter
which is GameCharacter
by calling GameCharacter
's constructor. Not doing this makes EyeCandyCharacter
's constructor call GameCharacter
's default constructor, which isn't defined, and therefore will result in an error.
As a sidenote, you can now, in C++11, directly use std::function
which have roughly the same functionality as std::tr1::function
.
Upvotes: 2
Reputation: 23644
For your second question:
Another question of mine here is that the initializer list in the constructor of the derived class usually only initializes the data members of itself (though I know the base part of the derived class is also intialized implicitly). How come the base class GameCharacter appears in the initializer of derived class EyeCandyCharacter?
No, if your base class does not have default constructor
defined, but has other constructors defined instead, you have to call based class constructor to initialize base class members. Since in this case, compile will not generate a default constructor
for you. In other words,
the base part of the derived class is NOT always initialized implicitly
Upvotes: 1