目前,我有以下管理不同类型变量的类:
class Variable;
class Number : public Variable;
class Boolean : public Variable;
class RealNumber : public Number;
class IntegerNumber : public Number;
这是一个经典的继承树,而且效果很好。我管理 Number*
的 vector Boolean*
的实例和 vector 实例。
我想添加另一种类型的变量:具有特定行为但具有相似接口(interface)的“虚拟变量”。然后,我想使用“虚拟数字” vector 和“虚拟 bool 值” vector 。
第一个解决方案是在 Variable
中添加一个标志, 但我更喜欢编译安全和管理 std::vector<VirtualResponse*>
和 std::vector<VirtualBoolean*>
为了保证变量在 vector 中是虚拟的。
然后,我想也许我处于多重继承合理的特定情况下,但我是多重继承的新手。 您如何看待这种类(class)?
class VirtualVariable : public virtual Variable;
class VirtualNumber : public virtual Number, public virtual VirtualVariable;
class VirtualBoolean : public virtual Boolean, public virtual VirtualVariable;
class VirtualRealNumber : public virtual RealNumber, public virtual VirtualNumber;
class VirtualIntegerNumber : public virtual IntegerNumber, public virtual VirtualVariable;
这是一种经典的方式吗?会不会是陷阱?我是否滥用了 virtual
关键词 ?
编辑:我想做的事的例子:
void my_function(const std::vector<SpecItem>& spec)
{
// First : create the description from the spec
std::vector<Number*> descr;
std::vector<VirtualNumber*> virt_descr;
for(unsigned long int i = 0; i < spec.size(); ++i)
{
if(spec[i].isNumber())
if(spec[i].isReal())
{
double lower_bound = spec[i].lowerBound();
double upper_bound = spec[i].upperBound();
if(spec[i].isVirtual())
{
std::string formula = spec[i].formula();
virt_descr.push_back(new VirtualRealNumber(lower_bound,upper_bound,formula));
}
else
descr.push_back(new RealNumber(lower_bound,upper_bound));
}
else if(spec[i].isInteger())
{
long int lower_bound = ceil(spec[i].lowerBound());
long int upper_bound = floor(spec[i].upperBound());
if(spec[i].isVirtual())
{
std::string formula = spec[i].formula();
virt_descr.push_back(new VirtualIntegerNumber(lower_bound,upper_bound,formula));
}
else
descr.push_back(new IntegerNumber(lower_bound,upper_bound));
}
}
// Now, descr is a vector of Number*, virt_descr is a vector of VirtualNumber*
// Second step : assign values to the numbers
std::vector<double> values;
for(unsigned long int i = 0; i < descr.size(); ++i)
{
double new_value = (descr[i]->lowerBound() + descr[i]->upperBound()) / 2.0;
values.push_back(descr[i]->adjust(new_value));
}
// Third step : evaluate virtual numbers
std::vector<double> virt_values;
for(unsigned long int i = 0; i < virt_descr.size(); ++i)
{
double new_value = virt_descr[i]->evaluate(values);
values.push_back(descr[i]->adjust(new_value));
}
return 0;
}
最佳答案
多重继承旨在通过确保 separation of concerns 来支持简洁的设计.所以可以说是天经地义。
如果不了解更多的原因和限制,就很难就最好的类设计提出建议。但有些问题可能对您有所帮助。
它从以下行开始:
class VirtualVariable : public virtual Variable;
1)是否需要虚继承?
在你来到虚拟继承之前,多重继承是非常简单和有趣的。这意味着对于从 VirtualVariable
多次继承的类,所有 VirtualVariable
子对象实例将共享一个 Variable
基础对象。有关更多信息,请阅读 diamond problem .
在您的设计中,您可能需要它用于 Variable
的每个继承(包括非“虚拟”的)以避免有多个 Variable
子对象,其中你真的应该只有一个。其他继承不需要它。
此虚拟继承将要求您为每个构造函数显式初始化您的虚拟基础。
2) Variable
和 VirtualVariable
之间的真正关系是什么?
根据您的解释,我了解到“虚拟”概念独立于“变量”概念。另一方面,在您的代码中,您假装 VirtualVariable
是一个 Variable
。
如果它是独立的东西,你应该保持它的独立性。这将是更好的关注点分离。好消息是您不再需要虚拟继承:
class Virtuality;
class VirtualVariable : public Variable, public Virtuality;
class VirtualNumber : public Number, public Virtuality;
class VirtualBoolean : public Boolean, public Virtuality;
class VirtualRealNumber : public RealNumber, public Virtuality;
class VirtualIntegerNumber : public IntegerNumber, public Virtuality;
3) 你看过模板了吗?
你说:
A first solution is adding a flag in Variable, but I prefer the compilation security and manage
如果只是为了编译类型检查,可以使用模板:
template <bool isvirtual>
Variable { ...};
template <bool isvirtual>
class Number : Variable<isvirtual> { ...};
...
std::vector<Number<true>*> v;
对于比变量更复杂的事物,您可以使用基于策略的设计。粗略地说,不是提供一个 bool 作为模板参数,而是提供一个实用程序类作为参数,该类封装了一系列行为。
编辑:供您编辑
解决方案 2 和 3 应该能够完美地实现您的意图。
我在这里张贴了一个 online demo 解决方案 2 的多态性,以演示您可以轻松混合“虚拟”和非“虚拟”元素。它定义了一个函数IntegerNumber add (IntegerNumber &a, IntegerNumber&b);
,并在这个场景中使用它:
IntegerNumber n(27); // number with an inital value
VirtualIntegerNumber k; // value will be calculated from some formula
add (n, k); // ok, my demo just displays the value of each parameter ;-)
*顺便说一下,我认为代码中的结构 if (isxxx())... if (isyyy()) ...
强烈建议您应该使用多态性。
关于c++ - 我是否在特定情况下证明多重继承是合理的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29920988/