Исключение виртуального деструктора, когда единственный производный класс не добавляет дополнительных переменных

У меня есть класс 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тогда вы можете присвоить ему отрицательное значение…

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

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

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

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


Приложение: я не смог увидеть, что в коде ОП значение const, Так что нет такой проблемы.

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

Другие вопросы по тегам