У меня есть класс Literal, который на самом деле просто оболочка для (const int). Я хочу иметь второй класс PositiveLiteral, который наследуется от Literal, но имеет конструктор, который утверждает, что его значение положительное.
class Literal {
public:
Literal(int x):x(x){}
virtual ~Literal(){}
// Other methods
private:
const int x;
}
class PositiveLiteral : public Literal {
public:
PositiveLiteral(int x):Literal(x) {
assert(x > 0)
}
}
Таким образом, функции, которые ожидают положительный литерал, могут просто принять PositiveLiteral в качестве аргумента. Тогда мне не нужно помещать явные утверждения в мой код, и, более того, там, где эти утверждения потерпят неудачу, я сразу понимаю, почему.
Я не ожидаю, что иначе унаследую от Literal, за исключением одного случая. Тем не менее, поскольку существует наследование, я должен дать Literal виртуальный деструктор, чтобы избежать неопределенного поведения, которое кажется глупым, потому что PositiveLiteral не имеет связанной с ним exra-информации, которой нет у Literal. Это просто способ поддержать утверждение, не делая его явным.
Как еще можно выполнить ту же задачу без использования виртуального метода, который должен быть простым классом-оберткой?
Вам не нужно иметь виртуальный деструктор, если вы не делаете динамическое распределение и delete
через указатель на базовый класс.
Настоящая проблема лежит на уровне дизайна. В то время как правда, что каждый PositiveLiteral
значение является Literal
значение, если у вас есть ссылка на Literal
который действительно PositiveLiteral
тогда вы можете присвоить ему отрицательное значение…
В литературе и на форумах это когда-то называлось проблемой эллипса и круга, хотя сходство не очевидно.
Во-первых, чтобы быть очень ясным о проблеме, это только для неизменные ценности это PositiveLiteral
это Literal
, это не случай, что изменчивый PositiveLiteral
изменчивый Literal
,
Затем практическое решение C ++ заключается в предоставлении преобразование стоимости вместо использования наследования.
Например, это решение, используемое для умных указателей.
добавление: Я не смог увидеть, что в коде ОП значение const
, Так что нет такой проблемы.
Практическая проблема состоит в том, что по крайней мере один компилятор, Visual C ++, имеет тенденцию глупо предупреждать о своей неспособности генерировать оператор присваивания копии; это можно закрыть, объявив частный без реализации. 🙂
Других решений пока нет …