抽象基类中初始化const成员变量的常用解决方案
Posted
技术标签:
【中文标题】抽象基类中初始化const成员变量的常用解决方案【英文标题】:Common solution for initializing const member variable in abstract base class 【发布时间】:2020-09-26 15:06:15 【问题描述】:鉴于以下情况
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_A
或Derived_B
的对象时,我想用Calc_Value()
初始化value_
。我知道只有Base
可以初始化它的 const 成员。现在,我的类对象主要是某种容器,它们在创建时计算必要的值。所以它们应该是只读的。
我知道我可以使 value_
不是 const,但这会使它变得可变。我在互联网上找到的大多数解决方案只是在Base
中创建一个额外的构造函数,但是我必须在基类中声明par3_
,这意味着,每次有一个derived_A
对象时,它都会有一个@987654331 @ 成员变量,而从未使用过它。另外,假设我想要更多具有不同Calc_Value()
函数的派生类,那么我是否需要为每个额外的子类声明一个构造函数?到目前为止,我已经通过将Calc_Value()
函数设为public 解决了这个问题,因此不需要public const 成员变量。但是在通过函数访问对象时,我认为圆括号会降低可读性,这就是为什么我希望在Base
中有一个 const 成员变量。
这个问题有通用的解决方案吗?
【问题讨论】:
如果是const
,则必须在构造函数初始化列表中进行初始化。
如果value_
的值只有派生类知道,为什么它是基类的成员?例如,您可以在 Base
中有一个纯虚拟 getValue
函数,并让派生类提供值。
请注意,要正确使用多态性,您需要在基类中定义一个虚拟析构函数。
@super value_
of base 需要包含计算值,否则myvector[idx]->value_
将不起作用或您的意思是什么?另外,您的意思是像Calc_Value()
这样的纯虚函数,但是是公开的?我这样做了,但我认为圆括号会降低可读性,这就是为什么我想要一个 const 成员。我只是想知道是否有我不知道的解决方案。我不是经验丰富的程序员。
@anastaciu 感谢 cmets!我想,我想做的事情是不可能的。是的,我忘记了示例中的析构函数。
【参考方案1】:
您可以在您的基类中有一个const 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::value
设为const
,则需要在构造函数初始化程序列表中对其进行初始化。如果您还需要一个函数来计算该值,则它不能是成员函数,因为在构造对象之前您不能调用成员函数。
在这种情况下,您可以将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;
;
看起来你只是为了避免此时写()
而让你的代码有点过于复杂。
【讨论】:
以上是关于抽象基类中初始化const成员变量的常用解决方案的主要内容,如果未能解决你的问题,请参考以下文章