子类如何调用以不同方式初始化成员变量的父类的构造函数? [C ++]

时间:2012-02-17 08:53:55

标签: c++ inheritance constructor

如何在其构造函数中计算子类的成员变量的值,然后传递给父的构造函数?

动机是,如果父类默认构造函数中有很多计算,那么我不想进行那些计算,只是将它们替换为子类后面计算的那些。

例如:

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

在这种情况下,尚未知道保时捷的价格。它必须在构造函数中计算。如果我这样调用父的构造函数,看起来它只会传递尚未初始化的价格。

传递一些只能在Child类初始化结束时知道的成员变量值的好方法???

4 个答案:

答案 0 :(得分:5)

很大程度上取决于实际情况,但一个常见的解决方案是 将所有计算卸载到静态成员中,因此您可以编写:

Porsche::Porsche()
    : Car( calclulatePrice() )
{
    //  ...
}

如果(如您的示例所示)您首先必须这样做,这将无效 在设置变量之前计算其他成员变量 基类。对于像您提出的那样的案例,最简单的解决方案 只是用0初始化基类,然后设置实际 价值以后。

更一般地说,我不得不怀疑你的设计。这不可能是正确的 基类和派生类都有一个成员price。 在最常使用的继承中,基类将是 抽象,没有数据成员。但即使不是这样,也是如此 基类的数据成员在派生中不重复 classes:如果派生类可以在任意中设置或更改它们 他们可能受到保护;否则,他们在基类中,并且 只能由基类中的函数操作(可以调用它) 来自派生类)。

答案 1 :(得分:4)

您不能这样做,在初始化数据成员之前和执行派生类构造函数的主体之前,首先在初始化顺序中执行基类构造函数。如果这些是昂贵的计算,那么最好的办法就是将它们从构造函数中移出。

编辑:技术上有一种方法可以解决这个问题,通过创建第二个构造函数,或者使用默认构造函数和默认参数值,可以用来停止基类中的计算,如下所示:

struct SkipCalculatePrice {};

class Car {
public:
    Car();
protected:
    Car(SkipCalculatePrice);
};

class Ferrari: public Car {
public:
    Ferrari(): Car(SkipCaluclatePrice()) [...]
[...]

但是,我个人不会建议这是一个好的设计实践。据了解,人们可能希望避免延迟初始化作为反模式,但是,对于昂贵的计算,正确完成延迟初始化可能是正确的答案:

class Car {
    virtual double calculatePrice();
    bool priceCalculated;
    double price;
public:
    double getPrice() {
        if(!priceCaluclated) {
            price = calculatePrice();
        }
        return price;
    }
}

class Ferrari: public Car {
    double calculatePrice();
};

答案 2 :(得分:1)

只需将计算代码从构造函数移动到实用程序函数,例如CalculatePrice( )。构造对象,然后调用此函数。

答案 3 :(得分:-1)

在父级的构造函数中使用虚方法来确定价格。在每个子类中重新定义此方法。