【发布时间】:2015-04-28 13:31:03
【问题描述】:
目前,我有以下类管理不同类型的变量:
class Variable;
class Number : public Variable;
class Boolean : public Variable;
class RealNumber : public Number;
class IntegerNumber : public Number;
这是一个经典的继承树,它运行良好。我管理Number* 实例的向量和Boolean* 实例的向量。
我想添加另一种类型的变量:具有特定行为但界面相似的“虚拟变量”。然后,我想使用“虚拟数字”向量和“虚拟布尔值”向量。
第一个解决方案是在Variable 中添加一个标志,但我更喜欢编译安全性并管理std::vector<VirtualResponse*> 和std::vector<VirtualBoolean*>,以保证变量在向量中是虚拟的。
然后,我想也许我在一个特定的情况下多重继承是合理的,但我是多重继承的新手。 您对这类课程有何看法?
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;
}
【问题讨论】:
-
我建议你看看这个multiple-inheritance example(在你能提供一个例子来演示上述指导方针吗?),看看是否有任何替代方案可以很好地工作给你。
-
我的观点是,如果不首先了解目标,就无法正确设计继承(多个或其他,虚拟或其他)。编写继承或面向对象的设计不能成为目标。那么这里的目标是什么?你想达到什么目的?
-
管理
std::vector<VirtualNumber*>和std::vector<VirtualBoolean*>对象的方式与我目前使用std::vector<Number*>的一些算法相同。VirtualVariables在评估时只有特定的行为,但从数学的角度来看保持相同的行为。 -
这不是信息。您使用的语言中,子类型关系和接口不仅限于继承,还有多种继承等。为了理解您的问题,需要解释类型的用例。你开始做的第一件事是,让 C++ 继承包装一个整数,这是值得怀疑的:即使是对 oo 上瘾的语言也会害怕。
标签: c++ inheritance multiple-inheritance