Передача std::unique_ptr в качестве параметра функции
Я получил структуру и функцию, подобную следующей:
struct MYOVERLAPPED : public OVERLAPPED
{
//...
};
void func1(std::unique_ptr<MYOVERLAPPED> pBuf)
{
//...
};
Я получаю указатель на MYOVERLAPPED, который я хочу передать функции func1. Проблема, с которой я сталкиваюсь, заключается в том, что независимо от того, что я пытаюсь, я получаю следующие ошибки:
То, что я уже пробовал, это следующее: Try1:
std::unique_ptr<OVERLAPPED> pOver(//....)
HandleAcceptIndication(std::move(pOver));
Ошибка: ошибка 1 ошибка C2440: "инициализация": невозможно преобразовать из "_OVERLAPPED **" в "MYOVERLAPPED *"
Try2:
HandleAcceptIndication(new ACCEPT_OVERLAPPED);
Ошибка 1 ошибка C2664: "HandleAcceptIndication": невозможно преобразовать параметр 1 из "MYOVERLAPPED *" в "std::unique_ptr<_Ty>"
Кто-нибудь знает, как я могу передать этот приведенный указатель OVERLAPPED в MYOVERLAPPED в функцию и почему Try2 тоже не работает, так как я случайно использую std::unique_ptr<MYOVERLAPPED> pO(new MYOVERLAPPED)
который работает...?
3 ответа
Пока вы не можете конвертировать из std::unique_ptr<base>
в std::unique_ptr<derived>
непосредственно, не так уж сложно написать функцию приведения, которая будет безопасна (то есть не утечет ресурс ни при каких обстоятельствах и будет успешной только в том случае, если приведение действительно:
template <typename Dst, typename Src>
std::unique_ptr<Dst> unique_dynamic_cast( std::unique_ptr<Src>& ptr ) {
Src * p = ptr.release(); // [1]
std::unique_ptr<Dst> r( dynamic_cast<Dst*>(p) ); // [2]
if ( !r ) {
ptr.reset( p ); // [3]
}
return r; // [4]
}
Основная идея заключается в том, что нам нужно извлечь указатель из std::unique_ptr
и отложите его в [1]. Мы не можем попробовать dynamic_cast
прямо, как будто это не удается, ptr
освободил бы владение, и память просочилась бы. Затем мы пытаемся выполнить dynamic_cast
[2] из локального указателя на запрошенный тип указателя и передать владение на r
результат уникальный указатель. Если dynamic_cast
не получается, тогда r
будет нулевым, и нам нужно вернуть владение памятью оригиналу std::unique_ptr
[3], для вызова кода, чтобы решить, что с ним делать. Затем мы возвращаем преобразованный std::unique_ptr
звонящему в [4].
Это не работает, потому что вы пытаетесь использовать неверный путь в иерархии наследования. Вы пытаетесь конвертировать из Base* в Derived* неявно.
unique_ptr<A>
а также unique_ptr<B>
несвязанные типы. Вы не можете конвертировать между ними, если не существует неявного преобразования между A*
а также B*
(спасибо UncleBens), что в данном случае неверно. Кроме того, вы не должны понижать иерархию наследования с экземпляром, который не является подклассом, к которому вы приводите. В этом случае вы пытаетесь разыграть OVERLAPPED
к MYOVERLAPPED
который является неверным приведением, потому что OVERLAPPED
это не MYOVERLAPPED
, Вот почему вы не можете конвертировать между unique_ptr
Типы в первую очередь.
Если вы просто пытаетесь передать unique_ptr
в func1
, вы можете сделать это так:
func1(shared_ptr<MYOVERLAPPED>(new MYOVERLAPPED));
Кроме того, передавая unique_ptr
для функции указатель в оригинале устанавливается в NULL. Рассмотрите возможность использования ссылок или shared_ptr
Если вы не создаете unique_ptr
в качестве временного и передачи его функции, и вам нужно использовать тот же экземпляр позже.