初始化抽象基类中常量成员变量的常见解决方案



给定以下情况

class Base
{
public:
Base(double par1, double par2)
:
par1_(par1),
par2_(par2)
{}
const double value_;
protected:
const double par1_, par2_;
virtual double Calc_Value() = 0;
};

class Derived_A : public Base
{
public:
Derived_A(double par1, double par2)
:
Base(par1, par2)
{}

protected:
double Calc_Value()
{
// <code to calc value with par1_ and par2_>
}
};

class Derived_B : public Base
{
public:
Derived_B(double par1, double par2, double par3)
:
Base(par1, par2),
par3_(par3)
{}
const double par3_;
protected:
double Calc_Value()
{
// <code to calc value with par1_, par2_ and par3_>
}
};
int main()
{
std::vector<Base*> my_vector;
// do stuff using polymorphism
}

这已经困扰我一段时间了。当创建Derived_ADerived_B的对象时,我想用Calc_Value()初始化value_。我知道只有Base可以初始化其常量成员。现在,我的类对象大多是某种容器,它们在创建时计算必要的值。所以它们应该是只读的。我知道我可以使value_不是常量,但这会使它可变。我在互联网上找到的大多数解决方案只是在Base中创建一个额外的构造函数,但随后我必须在基类中声明par3_,这意味着,每次有derived_A对象时,它都会有一个par3_成员变量,而不必使用它。此外,想象一下,我想拥有更多具有不同Calc_Value()函数的派生类,那么我需要为每个额外的子类声明一个构造函数吗?到目前为止,我只将Calc_Value()函数设置为公共就克服了这个问题,因此不需要public const成员变量。但在我看来,当通过函数访问对象时,圆括号会降低可读性,这就是为什么我希望在Base中有一个const成员变量。

这个问题有共同的解决方案吗?

您可以在基类中有一个const double&,并将double存储在派生类中。像这样的东西。

#include <iostream>
struct Foo {
Foo(const double& ref) : value(ref) {}
const double& value;
};
struct Bar : Foo {
Bar(const double p1, const double p2) : Foo (value), value(p1 + p2) {}
private:
double value;
};
int main() {
Bar b(5, 3);
Foo* f = &b;
std::cout << f->value;
}

这里允许Bar修改value,但由于Base有一个const-ref,所以不能使用引用修改值。

如果您也需要Bar::valueconst,则需要在构造函数初始化器列表中对其进行初始化。如果您还需要一个函数来计算该值,那么它就不能是成员函数,因为在构建对象之前,您不能调用成员函数。

在这种情况下,您可以使Calc_value成为一个静态成员函数,并从Bar的构造函数中向其传递所需的参数

struct Bar : Foo {
Bar(const double p1, const double p2) : Foo (value), value(Calc_value(p1, p2)) {}
private:
static double Calc_value(const double p1, const double p2) {
return p1 + p2;
}
double value;
};

似乎只是为了避免此时编写()而使代码过于复杂。

最新更新