Передача std :: unique_ptr в качестве параметра функции - PullRequest
1 голос
/ 09 сентября 2011

У меня есть структура и функция, подобная следующей:

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 ]

11 голосов
/ 09 сентября 2011

Хотя вы не можете конвертировать из 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].

2 голосов
/ 09 сентября 2011

Это не работает, потому что вы пытаетесь использовать неверный путь в иерархии наследования.Вы пытаетесь конвертировать из Base * в Derived * неявно.

0 голосов
/ 09 сентября 2011

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 s, если вы не создаете unique_ptr как временный объект и не передаёте его функции, и вам нужно использовать тот же экземпляр позже.

...