RAII классы с временными ресурсами - PullRequest
0 голосов
/ 04 ноября 2018

Я довольно новичок во многих современных концепциях C ++ / OOP, и у меня есть вопрос о дизайне RAII.

Рассмотрим класс, который управляет и взаимодействует с переходным ресурсом: соединение через сокет TCP, соединение с устройством Bluetooth и связь с указанными устройствами. Вещи как это. Мы можем предположить, что класс полностью бесполезен, если ресурс недоступен или становится недоступным.

Я не могу решить, является ли RAII (в частности, получение / подключение к ресурсу в ctor) хорошим или плохим для этого типа класса.

С одной стороны, если функциональность класса зависит от ресурса, кажется, имеет смысл выбросить из ctor, а не при более позднем вызове Connect (). С другой стороны, получение переходного ресурса обычно включает в себя некоторую блокировку и / или асинхронную операцию, что для меня похоже на плохой дизайн конструктора.

Я нашел несколько других тем, которые танцуют вокруг этого вопроса, но не полностью удовлетворили мое любопытство: RAII, сокеты Беркли и контейнеры STL

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

Будем благодарны за любые рекомендации по передовому опыту!

РЕДАКТИРОВАТЬ: Уточнение моего вопроса на основе комментариев ниже. С частью RAII, которая имеет дело с конструкторами, устанавливающими все инварианты класса - соединение с устройством является инвариантом, потому что класс должен гарантировать, что все открытые методы, которые пытаются связаться с этим устройством, действительны после построения. ОДНАКО - действительно ли это можно считать инвариантом класса, поскольку программа не контролирует доступность удаленного устройства?

1 Ответ

0 голосов
/ 05 ноября 2018

Если у ресурса может быть «пустое» состояние, вполне разумно, чтобы класс, владеющий этим ресурсом, имел конструктор по умолчанию (и acquire и release методы).

Все члены, которые должны проверять наличие непустых значений, указывают, что класс не может с пользой иметь "пустое" состояние, и оно не должно быть DefaultConstructable , и должно быть Подвижным , если оно С возможностью копирования .

Обычно вы также имеете конструктор, acquire d.

Это нормально для асинхронного конструирования чего-либо, хотя это будет включать оборачивание конструкции в асинхронную функцию.

template <typename T, typename ... Args>
std::future<T> constructAsync(Args&& args...)
{
    return std::async([](Args&& args...) { return T(std::forward<Args>(args)...); }, std::forward<Args>(args)...);
}

int main()
{
    auto foo = constructAsync<Foo>();
    auto bar = constructAsync<Bar>("some", "params");

    foo.get().frob(bar.get()); // only occurs when both are ready
}
...