0

У меня есть класс 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 не имеет. Это просто способ поддержать утверждение, не делая его явным.

Какой еще способ выполнить ту же задачу без необходимости использования виртуального метода в том, что должно быть простым классом-оболочкой?

ответ

1

Вам не нужно иметь виртуальный деструктор, если вы не выполняете динамическое выделение и delete с помощью указателя на базовый класс.


Реальная проблема заключается в уровне разработки. В то время как верно, что каждое значение PositiveLiteral является значением Literal, если у вас есть ссылка на Literal, который действительно является PositiveLiteral, тогда вы можете присвоить ему отрицательное значение & hellip;

В литературе и обсуждениях в форуме это когда-то называлось проблемой эллипса против круга, хотя сходство не очевидно.

Во-первых, очень четкое представление о проблеме, это только для неизменных значений что PositiveLiteral представляет собой Literal. Это не случай, что изменчивый PositiveLiteral является изменчивым Literal.

Тогда практическое решение на С ++ должно обеспечить преобразование значения вместо использования наследования.

Например, это решение, используемое для интеллектуальных указателей.


Добавление: Я не смог увидеть, что в коде OP в значение const. Поэтому нет такой проблемы.

Практическая проблема заключается в том, что хотя бы один компилятор Visual C++ имеет тенденцию глупо предупреждать о своей неспособности создать оператор присваивания копии; его можно заткнуть, объявив частный, без реализации. :-)

+0

Спасибо, я не был полностью уверен в этом (если я правильно понял, вы говорите, что даже при наличии полиморфизма мне не нужен виртуальный деструктор, если деструктор по умолчанию будет достаточным) , Обратите внимание, что x является const в моем классе Literal, поэтому значения действительно неизменяемы. Тем не менее, что вы подразумеваете под «преобразованием ценности»? Я googled «преобразование значений на C++», и ни одна из первых ссылок на пару, похоже, не применима здесь. – dspyz

+0

@dspyz: О, я не видел, что это 'const'. второй «не смог увидеть» сегодня утром на SO. Мне определенно нужно больше кофе! –

+0

Преобразование значений здесь, где у вас есть, например. 'operator Literal() const' в классе PositiveLiteral', чтобы обеспечить неявное преобразование в 'Literal'. Он также может быть выражен с помощью конструктора 'Literal' с аргументом PositiveLiteral'. –