Я возвращаюсь к C++ после большого опыта работы с C# и унаследовал некоторую кодовую базу C++, которая, по моему мнению, могла не соответствовать лучшим практикам C++.
Для Например, я имею дело со следующим случаем (упрощенно):
// resource
class Resource {
HANDLE _resource = NULL;
// copying not allowed
Resource(const Resource&);
Resource& operator=(const Resource& other);
public:
Resource(std::string name) {
_resource = ::GetResource(name); if (NULL == _resource) throw "Error"; }
~Resource() {
if (_resource != NULL) { CloseHandle(_resource); _resource = NULL; };
}
operator HANDLE() const { return _resource; }
};
// resource consumer
class ResourceConsumer {
Resource _resource;
// ...
public:
void Initialize(std::string name) {
// initialize the resource
// ...
// do other things which may throw
}
}
Здесь ResourceConsumer создает экземпляр Resource и выполняет некоторые другие действия. По какой-то причине (вне моего контроля) для этого он предоставляет метод Initialize вместо того, чтобы предлагать конструктор не по умолчанию, что, очевидно, нарушает шаблон RAII. Это библиотечный код, и API не может быть реорганизован без внесения критических изменений.
Итак, мой вопрос: как правильно закодировать Initialize в этом случае? Приемлема ли практика использования строительства/разрушения на месте и повторного броска, как показано ниже? Как я уже сказал, я пришел из C#, где для этого я просто использовал try/finally или шаблон using.
void ResourceConsumer::Initialize(std::string name) {
// first destroy _resource in-place
_resource.~Resource();
// then construct it in-place
new (&_resource) Resource(name);
try {
// do other things which may throw
// ...
}
catch {
// we don't want to leave _resource initialized if anything goes wrong
_resource.~Resource();
throw;
}
}
Подробнее здесь: https://stackoverflow.com/questions/522 ... t-possible
Как сделать «попробовать/наконец» на C++, если RAII невозможен? ⇐ C++
-
- Похожие темы
- Ответы
- Просмотры
- Последнее сообщение