Нашли или выдавили из себя код, который нельзя назвать нормальным,
на который без улыбки не взглянешь?
Не торопитесь его удалять или рефакторить, — запостите его на
говнокод.ру, посмеёмся вместе!
Петухи, подскажите ламеру. Этот вопрос обсуждался наверняка.
В крестах у меня полетело исключение из середины конструктора. Это значит, что объект как-бы наполовину сконструирован. Но десктрутор же его не вызовется?
Как мне очистить ресурсы?
Допустим, я в конструкторе создал какую-то структуру операционной системы:
PETUH_HANDLE CreatePetuh();
Теперь я должен сделать ReleasePetuh(); Но на следующем шаге полетело исключение.
Я не могу релизнуть петуха -- деструктор не вызывается.
Я могу вынести конечно питуха в отдельный класс, но не хочу.
Как верно поступить?
Я могу конечно не делать этого в конструкторе: просто инициализировать питуха nullptrом, и установить его в каком-то методе типа Initialize()
1) использовать try catch в конструкторе
2) использовать инициализацию для полей - для них вызовется деструктор (напиши класс scoped_handle или вообще используй средства shared/unique ptr для нетривиальных способов деструкции)
>1) использовать try catch в конструкторе
Тогда как я сообщу вызывающей стороне, что создать объект не удалось? По какому-то булеву полю?
> использовать инициализацию для полей
Так поле же у меня просто поинтер или вообще инт: это или хендл структуры оперционки (сишного API) или смещение в таблице дескрипторов моего процесса, в общем внешний НЕ RAII
ресурс
>scoped_handle
вот сюда посмотрю, спасибо
>"Тогда как я сообщу вызывающей стороне, что создать объект не удалось? По какому-то булеву полю?"
Не ебу в "C++", но, исходя из опыта разработки на "PHP", предлагаю перед "try" создать переменную типа "objectCreated" со значением "false", а внутри "try" присваивать ей значение "true".
Ты должен подчистить за собой как минимум, и раз уж ты пошел по скользкому пути ебошить исключения в конструкторе - то можно наконец делать throw и из своего, чтобы охуел уже тот, кто пытается твой класс юзать
Да у меня-то подгорает от такой инициализации, потому что во-первых лишние действия, во-вторых объект получается может находиться в двух состояниях, и все мутабл.
Потом еще вон булево поле завозить objectCreated (как советует ротоёб)
> объект получается может находиться в двух состояниях
В этом и жопа. Куча возможностей для отстрела яиц - забыл позвать инит, забыл обработать ошибку инита, забыл закопать мёртвый объект. А с исключением у тебя всегда инвариант "если есть объект, значит можно с ним работать".
Угу. Даже у нас в джавке это считается некрасивым. Лучше когда все поля финальные, и все устанавливаются в конструкторе. Ну вот я подумал, как это принято делать в С++, и вижу, что так же.
А можно сделать конструктор приватным, а объекты создавать только в виде умного указателя статическим методом. Получил пустой указатель - у вас ошибка, разгребайтесь.
Потому что для жирных объектов насрать на оверхед. А с интерфейсом и юнит-тестик можно хуйнуть и из реализации кишки всякого винапи, позикса и прочего дерьма не торчат.
Предлагаю перейти на "PHP". Нет принуждения к ебучему ООП, можно писать в ясном и понятном процедурном стиле, безо всяких конструкторов, полей, объектов, исключений и остального говна.
bootcamp_dropout # 0
3oJIoTou_xyu # 0
guest # 0
В крестах у меня полетело исключение из середины конструктора. Это значит, что объект как-бы наполовину сконструирован. Но десктрутор же его не вызовется?
Как мне очистить ресурсы?
Допустим, я в конструкторе создал какую-то структуру операционной системы:
PETUH_HANDLE CreatePetuh();
Теперь я должен сделать ReleasePetuh(); Но на следующем шаге полетело исключение.
Я не могу релизнуть петуха -- деструктор не вызывается.
Я могу вынести конечно питуха в отдельный класс, но не хочу.
Как верно поступить?
Я могу конечно не делать этого в конструкторе: просто инициализировать питуха nullptrом, и установить его в каком-то методе типа Initialize()
Но не хочу.
Как правильнее поступить?
bormand # 0 ⇈
Но у локалок деструктор сработает. У полей, которые успели создаться - тоже. Ну и у базовых классов.
Поэтому складывай всё что насоздавал сразу в RAII'шную хуйню в локалках или в полях. И всё будет норм.
guest # 0 ⇈
Завернуть каждый PETUH_HANDLE в отдельный класс?
bormand # 0 ⇈
defecate-plusplus # 0 ⇈
2) использовать инициализацию для полей - для них вызовется деструктор (напиши класс scoped_handle или вообще используй средства shared/unique ptr для нетривиальных способов деструкции)
guest # 0 ⇈
Тогда как я сообщу вызывающей стороне, что создать объект не удалось? По какому-то булеву полю?
> использовать инициализацию для полей
Так поле же у меня просто поинтер или вообще инт: это или хендл структуры оперционки (сишного API) или смещение в таблице дескрипторов моего процесса, в общем внешний НЕ RAII
ресурс
>scoped_handle
вот сюда посмотрю, спасибо
MOXHATKA # 0 ⇈
Не ебу в "C++", но, исходя из опыта разработки на "PHP", предлагаю перед "try" создать переменную типа "objectCreated" со значением "false", а внутри "try" присваивать ей значение "true".
guest # 0 ⇈
bormand # 0 ⇈
У тебя же исключение вылетело. Вызывающий код твой недостроенный объект никогда не увидит.
guest # 0 ⇈
bormand # 0 ⇈
defecate-plusplus # 0 ⇈
guest # 0 ⇈
В общем я всё сам почистил, и потом их бросил.
А как не бросать исключения? Делать тупой конструктор, и всю логику уносить в метод типа Initialize() ?
bormand # 0 ⇈
Да, но лучше брось. Впизду эту джхвухфазную инициализацию, с ней всегда куча ёбли и багров. Её не от хорошей жизни делают.
guest # 0 ⇈
Потом еще вон булево поле завозить objectCreated (как советует ротоёб)
MOXHATKA # 0 ⇈
Оно так мешает?
guest # 0 ⇈
Типа раз есть объект -- значит он инициализирован
Хотя для двухфазной инициализации оно ок
bormand # 0 ⇈
В этом и жопа. Куча возможностей для отстрела яиц - забыл позвать инит, забыл обработать ошибку инита, забыл закопать мёртвый объект. А с исключением у тебя всегда инвариант "если есть объект, значит можно с ним работать".
DypHuu_niBEHb # 0 ⇈
bormand # 0 ⇈
Можно и через аргумент конструктора код ошибки вернуть, лол 😉
guest # 0 ⇈
Удобно!
причем деструктор-то у него вызовется!
defecate-plusplus # 0 ⇈
guest # 0 ⇈
Мы в джавке так делаем, что бы не утёк this, если нужно созданный объект сразу где-то зарегистрировать.
MOXHATKA # 0 ⇈
bormand # 0 ⇈
guest # 0 ⇈
А зачем? Чтобы не ебаться с копированием и референсами при передаче? Или чтобы стек не рвать?
bormand # 0 ⇈
guest # 0 ⇈
Pointer у тебя на интерфейс IFoo, класс реализован в IFooImp, реализация клиенту не видна. Правда, все методы получаются виртуальные, но всем похуй?
Fike # 0 ⇈
мы опять про тиндер?
KOMAPuK # 0 ⇈
MOXHATKA # 0 ⇈
guest # 0 ⇈
Да в общем даже в джаве с с# его нет, хотя и рекомендуется