C++ 子类如何调用初始化成员变量的父类的构造函数?[C+;+;]
如何在子类的构造函数中计算其成员变量的值,然后传递给父类的构造函数 这样做的动机是,如果父类默认构造函数中有大量计算,那么我不想做这些计算,只想让子类立即将它们替换为子类计算的结果 例如: 汽车 Car.cppC++ 子类如何调用初始化成员变量的父类的构造函数?[C+;+;],c++,inheritance,constructor,C++,Inheritance,Constructor,如何在子类的构造函数中计算其成员变量的值,然后传递给父类的构造函数 这样做的动机是,如果父类默认构造函数中有大量计算,那么我不想做这些计算,只想让子类立即将它们替换为子类计算的结果 例如: 汽车 Car.cpp Car::Car() { //some other long computation price = DetermineMarketPrice(); } Car::Car(double Price) { price = Price; } ... 门廊 clas
Car::Car()
{
//some other long computation
price = DetermineMarketPrice();
}
Car::Car(double Price)
{
price = Price;
}
...
门廊
class Porche : public Car
{
public:
Porche();
...
private:
double price;
double discount;
double fee;
double DetermineMarketPrice();
double RetrieveFee();
double CheckDiscount();
...
};
波切
Porche::Porche():Car(price)
{
discount = CheckDiscount();
fee = = RetrieveFee();
price = DetermineMarketPrice() * (1-discount) + fee;
}
在这种情况下,门廊的价格还不得而知。它必须在构造函数中计算。如果我像这样调用父级的构造函数,它似乎只传递尚未初始化的价格
传递某些成员变量值的好方法是什么?这些值只能在子类初始化结束时才知道?只需将计算代码从构造函数中移到实用函数中,如
CalculatePrice()
。构造对象,然后调用此函数。在父对象的构造函数中使用虚方法来确定价格。在每个子类中重新定义此方法 您不能这样做,基类构造函数首先按照初始化顺序执行,然后是数据成员初始化,然后是派生类构造函数的主体执行。如果这些计算成本很高,那么最好将它们移出构造函数
编辑:从技术上讲,有一种方法可以解决这个问题,方法是创建第二个构造函数,或者使用一个带有默认参数值的默认构造函数,它可以用来停止基类中的计算,如下所示:
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();
};
这在很大程度上取决于实际情况,但一个常见的解决方案是 将所有计算卸载到静态成员中,以便您可以编写:
Porsche::Porsche()
: Car( calclulatePrice() )
{
// ...
}
如果(如你的例子所示)你首先必须这样做,那么这是行不通的
在中设置变量之前,计算其他成员变量
基类。对于您所介绍的情况,最简单的解决方案
就是用0初始化基类,然后设置实际的
以后再估价
一般来说,我想知道你的设计。这不可能是对的
基类和派生类都有一个成员price
。
在最常用的继承中,基类将是
抽象,没有数据成员。但即使情况并非如此
基类的数据成员在派生类中不重复
类:如果派生类可以以任意方式设置或更改它们
这样,他们就可以得到保护;否则,它们在基类中,并且
仅由基类中的函数操作(可以调用
在构造函数中调用虚方法不会像这样工作,因为调用该方法时还没有创建子对象。这不起作用,从构造函数调用虚函数时,将调用基类的函数,不是派生的。为什么要将昂贵的计算移出构造函数?@fdlm:详细讨论了这个问题。在这种情况下,这个问题有一个实用的和哲学的答案。从实用的角度来看,基构造函数被称为派生类构造的第一阶段,因此在那里进行既昂贵又不必要的计算是浪费的。从哲学设计的角度来看,Car类代表了什么使一辆车成为一辆车,构造器设置了所有车都通用的东西。如果法拉利是一辆汽车,而按汽车类别计算的价格不适用于法拉利,那么这不是所有汽车的共同点。我明白你的意思。Car的构造函数(父类)实际上应该只对Car的所有类型(子类)通用的东西进行初始化。但在这种情况下,既然价格必须计算出来,那么把它放在构造函数中是否合乎逻辑呢?否则,程序员在声明Car对象时需要记住做两件事。如果我想将对象用作其他函数的参数,它将不起作用。请注意第二个延迟计算示例:程序员不必记住计算价格,它将在程序首次尝试访问价格时计算。您能确定MarkedPrice,RetrieveFee和CheckDiscount static?除此之外,
double
不适合花钱。lots\u of pennies*0.01
的值不一定等于lots\u of pennies/100
。感谢您的评论和建议!现在我意识到,与其把它当作一个技术问题来处理,不如把它当作一个设计问题来处理。尽管有办法解决这个问题,但我认为派生类应该只是具有附加规范或函数的父类。继承并不意味着将做不同事情的两个类视为一个类。我想我要做的是创建另一个更通用的类,作为这两个类的父类。但是,我知道每次“制造”一辆车时,我都需要计算价格。如果程序员在创建对象之后忘记使用CalculatePrice()函数,那么价格将不会初始化,并可能导致其他一些错误。这就是为什么我试图在构造函数中完成所有工作,因为它无论如何都必须完成。在这种情况下,创建一个工厂,该工厂同时构造车辆并调用计算函数。price
变量可以被保护或管理
Porsche::Porsche()
: Car( calclulatePrice() )
{
// ...
}