Функция преобразования для проверки ошибок считается хорошей?
Я хотел бы иметь простой способ проверки, чтобы объект был действительным. Я подумал о простой функции преобразования, что-то вроде этого:
operator bool() const { return is_valid; }
Проверить, чтобы он был действительным, было бы очень просто
// is my object invalid?
if (!my_object) std::cerr << "my_object isn't valid" << std::endl;
Это считается хорошей практикой?
3 ответа
В C++03 вам нужно использовать идиому безопасной bool, чтобы избежать зла:
int x = my_object; // this works
В C++11 вы можете использовать явное преобразование:
explicit operator bool() const
{
// verify if valid
return is_valid;
}
Таким образом, вы должны четко указывать на преобразование в bool, чтобы вы больше не могли делать сумасшедшие вещи случайно (в C++ вы всегда можете делать сумасшедшие вещи специально):
int x = my_object; // does not compile because there's no explicit conversion
bool y = bool(my_object); // an explicit conversion does the trick
Это все еще работает как обычно в таких местах, как if
а также while
которые требуют логического выражения, потому что условие этих операторов контекстно преобразуется в bool:
// this uses the explicit conversion "implicitly"
if (my_object)
{
...
}
Это задокументировано в §4 [conv]:
Выражение
e
может быть неявно преобразован в типT
если и только если декларацияT t=e;
правильно сформирован, для некоторой придуманной временной переменнойt
(§8.5). Некоторые языковые конструкции требуют преобразования выражения в логическое значение. Выражениеe
говорят, что в таком контексте контекстуально преобразуется вbool
и является правильным, если и только если декларацияbool t(e);
правильно сформирован, для некоторой придуманной временной переменнойt
(§8.5). Эффект любого неявного преобразования аналогичен выполнению объявления и инициализации, а затем использованию временной переменной в качестве результата преобразования.
(Что делает разницу в использовании bool t(e);
вместо bool t = e;
.)
Места, где происходит это контекстное преобразование в bool:
- условия
if
,while
, а такжеfor
заявления; - операторы логического отрицания
!
логическое соединение&&
и логическая дизъюнкция||
; - условный оператор
?:
; - состояние
static_assert
; - необязательное константное выражение
noexcept
спецификатор исключения;
Нет, простого оператора преобразования bool нет, так как теперь вы можете проводить злые сравнения между несвязанными типами. Как правило, да, функция преобразования - это нормально. Просто используйте правильный ( идиома "безопасный бул"). Я не могу объяснить это лучше, чем приведенные ссылки.
Первоначальный вопрос был
Это считается хорошей практикой?
Проблема с безопасным преобразованием bool была очень актуальна на практике, но, к счастью, теперь она была решена стандартами.
Но суждение, если этот подход уместен, является вопросом дизайна.
Вводя такую "проверку достоверности", вы фактически заявляете, что ваши объекты могут находиться в недопустимом состоянии. То есть, говоря с точки зрения информатики, вы добавили новое отдельное значение в область значений, представленную вашими объектами. Так называемое нижнее значение
Наиболее ярким примером для области значений с таким свойством является указатель. Указатель может ссылаться на различные области памяти, но также может быть NULL
(недействительным).
Таким образом, мы должны спросить себя: действительно ли такое нижнее значение отражает природу вещей, которые мы хотим смоделировать с помощью наших классов - и - действительно ли нам нужно охватить этот аспект природы в нашей модели?
Опыт показывает, что нижние значения, как правило, подвержены ошибкам, легко забываются и, как правило, являются скорее пассивом, чем активом. Если вы можете организовать свой код таким образом, чтобы ваши объекты не могли быть недействительными, ваш код становится проще, его легче читать, понимать и поддерживать.