Reputation: 1149
How can I compute the value of a child class's member variable in it's constructor, and then pass on to the parent's constructor??
The motivation is that, if there's a lot of calculation in the parent class default constructor, then I don't want to have to do those calculation and only have them replaced by those computed by child class right after.
For example:
Car.h
class Car
{
public:
Car();
Car(double Price) ;
...
private:
double price;
double DetermineMarketPrice();
};
Car.cpp
Car::Car()
{
//some other long computation
price = DetermineMarketPrice();
}
Car::Car(double Price)
{
price = Price;
}
...
Porche.h
class Porche : public Car
{
public:
Porche();
...
private:
double price;
double discount;
double fee;
double DetermineMarketPrice();
double RetrieveFee();
double CheckDiscount();
...
};
Porche.cpp
Porche::Porche():Car(price)
{
discount = CheckDiscount();
fee = = RetrieveFee();
price = DetermineMarketPrice() * (1-discount) + fee;
}
In this case, the price of a Porche isn't known yet. It has to be calculated in the constructor. If I call the parent's constructor like this, seems like it would only pass the not-yet-initialized price.
What would be a good way to pass some value of member variables that can only be known at the end of the Child class initialization???
Upvotes: 2
Views: 19501
Reputation: 740
You can't do that, the base class constructors are executed first in the initialisation order, before data members are initialised and before the derived class constructor's body is executed. If these are costly calculations, the best thing to do may be moving them out of the constructor.
EDIT: There's technically a way to work around this problem, by creating a second constructor, or having a default constructor with a default parameter value, which can be used to stop the calculations in the base class, like so:
struct SkipCalculatePrice {};
class Car {
public:
Car();
protected:
Car(SkipCalculatePrice);
};
class Ferrari: public Car {
public:
Ferrari(): Car(SkipCaluclatePrice()) [...]
[...]
However, I personally would not recommend this as a good design practice. It is understood that one would want to avoid delayed initialization as an anti-pattern, however, for costly calculations, properly done lazy initailization might be the right answer:
class Car {
virtual double calculatePrice();
bool priceCalculated;
double price;
public:
double getPrice() {
if(!priceCaluclated) {
price = calculatePrice();
}
return price;
}
}
class Ferrari: public Car {
double calculatePrice();
};
Upvotes: 5
Reputation: 25799
Just move the calculation code out of the constructor to a utility function such as CalculatePrice( )
. Construct the object and then call this function.
Upvotes: 1
Reputation: 153909
A lot depends on the actual situation, but one frequent solution is to offload all of the calculations into a static member, so you can write:
Porsche::Porsche()
: Car( calclulatePrice() )
{
// ...
}
This won't work if (as your example suggests) you first have to calculate other member variables, before setting the variable in the base class. For cases like the one you present, the simplest solution is just to initialize the base class with 0, and then set the actual value later.
More generally, I have to wonder about your design. It can't be right
that both the base class and the derived class have a member price
.
In the most frequent use of inheritance, the base class will be
abstract, with no data members. But even when this is not the case, the
data members of the base class are not duplicated in the derived
classes: if the derived classes can set or change them in an arbitrary
way, they may be protected; otherwise, they are in the base class, and
only manipulated by functions in the base class (which may be called
from the derived class).
Upvotes: 5
Reputation: 22890
Use an virtual method in the constructor of the parent to determine the price. Redefine this method in each child class.
Upvotes: -1