我们正在我们的项目中尝试使用有界原始类型
,我们可以在其中检查派生类的实例是否具有有效范围内的数据值(min
和 max
成员变量,在派生 class
的基 class
中受到保护。
我的问题是,有没有一种方法可以静态初始化派生类的 min
和 max
变量,每个派生的 class
只需一次,而不是每次我实例化派生的类
。
在 C#
中,这将在静态初始化 block 中,但我不确定如何在 C++
中执行此操作。
我知道我可以在派生的类构造函数
中初始化它们,但每次都这样做似乎很浪费。
我想我正在寻找抽象数据成员,在基类中声明,但随后在派生类中静态定义。
class BoundedFloat
{
public:
BoundedFloat(const float v) : Value(v) {}
// some common methods that use Min and Max
// prefer to implement in base class rather than in each derived class
bool withinBounds();
bool breachedLowerThreshold();
bool breachedUupperThreshold();
protected:
const float Min;
const float Max;
float Value;
}
bool BoundedFloat::withinBounds()
{
return ((Value >= Min) && (Value<= Max));
}
bool BoundedFloat::breachedLowerThreshold()
{
return (Value < Min);
}
bool BoundedFloat::breachedUupperThreshold()
{
return (Value > Max);
}
class Temperature : public BoundedFloat
{
public:
Temperature(const float v) : BoundedFloat(v) {}
// seems wasteful to do this each time, when min and max only need
// initialised once per derived class
// Temperature(const float v) : BoundedFloat(v, -40.0f, 80.0f)
// statically initialise Temperature's Min and Max in base class here somehow?
private:
// I know this is wrong, but it indicates the functionality I'm looking for.
override static float Min;
override static float Max;
}
最佳答案
我认为除了进行一些重新设计外,没有任何方法可以完全按照您的要求进行操作。请记住,对于未标记为 static
的成员,类类型的每个对象都有自己的这些成员拷贝。如果您有多个类型为 Temperature
的对象,每个对象都有自己的 Min
和 Max
,因此所有这些对象都需要在某个时候进行初始化。此外,基类 BoundedFloat
无法知道它被用于几个可能的派生类中的哪一个,除非你以某种方式让它知道,并且只传递最小值和最大值可能是最简单的方法“让它知道”。
但是与此相关的“浪费”(编码和维护工作?CPU 运行时?成员变量使用的内存?)对我来说似乎并不那么大。
不过,您可能需要考虑一些重新设计的选项:
将数据从成员更改为虚拟 getter 函数。
class BoundedFloat { public: BoundedFloat(const float v) : Value(v) {} virtual ~BoundedFloat() = default; protected: BoundedFloat(const BoundedFloat&) = default; BoundedFloat(BoundedFloat&&) = default; BoundedFloat& operator=(const BoundedFloat&) = default; BoundedFloat& operator=(BoundedFloat&&) = default; float Min() const = 0; float Max() const = 0; float Value; }; class Temperature : public BoundedFloat { public: Temperature(const float v) : BoundedFloat(v) {} float Min() const override { return -40.0f; } float Max() const override { return 80.0f; } };
现在每个派生类都单独负责其最小/最大值。尽管这种方法有其自身的成本,这对您来说可能重要也可能不重要。
享元模式
class BoundedFloat { protected: struct Data { float Min; float Max; }; BoundedFloat(const float v, const Data& data_in) : Value(v), data(data_in) {} protected: BoundedFloat(const BoundedFloat&) = default; BoundedFloat(BoundedFloat&&) = default; BoundedFloat& operator=(const BoundedFloat&) = default; BoundedFloat& operator=(BoundedFloat&&) = default; float Value; const Data& data; }; class Temperature : public BoundedFloat { public: Temperature(const float v) : BoundedFloat(v, my_data) {} private: static const Data my_data; }; const Temperature::Data Temperature::my_data{ -40.0f, 80.0f };
这里只有一个派生类数据值的初始化,它们几乎自然地“在”基类中;只需将它们命名为
data.Min
和data.Max
。当每个类都有大量数据时,通常会使用此模式,但您当然也可以只使用少量数据。这里的编码成本与传递单个基值相当,或者可能更低,并且程序的运行时成本可能会有所上升或下降,具体取决于。
关于C++ - 在派生类中静态初始化基类保护的成员变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55495264/