В настоящее время у меня есть следующие классы управления различными видами переменных:Я в конкретном случае оправдываю многократное наследование?
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
?
EDIT: пример того, что я хочу сделать:
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;
}
Я рекомендую вам ознакомиться с этим [примером нескольких наследований] (https://isocpp.org/wiki/faq/multiple-inheritance#mi-example) (в разделе * Можете ли вы привести пример, демонстрирующий вышеприведенное руководящие принципы? *) и посмотрите, может ли какой-либо из альтернатив работать для вас. –
Мое мнение состоит в том, что наследование (множественное или иное, виртуальное или иное) не может быть правильно спроектировано, не понимая сначала * цели *. Написание наследования или объектно-ориентированного дизайна * не может быть целью. Так в чем же цель? Чего вы пытаетесь достичь? – Nawaz
Управляйте объектами 'std :: vector' и 'std :: vector ' так же, как я в настоящее время использую 'std :: vector ' с некоторыми алгоритмами. «VirtualVariables» имеет только определенное поведение при оценке, но сохраняет то же поведение для математической точки зрения. –
Caduchon