2013-08-23 3 views
7

Предположим, у меня есть класс foo, который наследуется от класса bar.Каков правильный способ преобразования std :: unique_ptr в std :: unique_ptr в суперкласс?

У меня есть std::unique_ptr экземпляру foo, и я хочу передать его функции, которая принимает только std::unique_ptr<bar>. Как я могу преобразовать указатель, чтобы он работал в моей функции?

+0

ли 'Foo' полиморфный экземпляр? – Mahesh

+2

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

+1

@NeilKirk: Эта работа для функции, но это разумный прецедент для хранения 'unique_ptr ' в коллекции. И если функция должна его хранить ... –

ответ

27

Вы можете преобразовать std::unique_ptr<foo> RValue к std::unique_ptr<bar>:

std::unique_ptr<foo> f(new foo); 
std::unique_ptr<bar> b(std::move(f)); 

Очевидно, что указатель будет принадлежать b и если b разрушается bar потребности иметь virtual деструктор.

-1

Вы не можете, так как это нарушит самое основное правило unique_ptr: должен быть только один экземпляр, который содержит данный указатель, и unique_ptr имеет полное право собственности на него (когда он выходит из сферы действия, удаляется).

unique_ptr<T> и unique_ptr<U> (где U : T) несовместимы, как вы видели.

Для shared_ptr, для которых вы можете иметь несколько экземпляров, есть std::static_pointer_cast, который ведет себя так же, как static_cast, за исключением того, что она принимает shared_ptr и возвращает другой (и оба указывают на тот же объект).

Если вам абсолютно необходимо использовать unique_ptr, вам необходимо создать функцию, которая сначала отключит ваш текущий unique_ptr и помещает этот указатель в новый подходящий тип. Вам также может потребоваться сделать обратное преобразование после вызова функции.

+1

+1. для полноты, 'std :: dynamic_pointer_cast <>' и 'std :: const_pointer_cast <>' существуют для других распространенных конверсий указателей. – justin

+3

Конечно, вы можете, вы просто должны передать право собственности, хотя, очевидно. –

+0

@ MatthieuM. «Если вам абсолютно необходимо использовать unique_ptr, вам нужно создать функцию, которая сначала отключит ваш текущий уникальный_ptr и помещает этот указатель в новый правильный тип». Моя точка зрения заключалась в том, что 'unique_ptr ' не может связываться с ссылкой 'unique_ptr '. Передача собственности точно так же не является исключением. – zneak

0

Вы можете использовать этот синтаксис:

std::unique_ptr<parent> parentptr = std::unique_ptr<child>(childptr); 

Или вы можете использовать std::move.

Другой вариант заключается в испускать сырой указатель, но вам необходимо изменить функцию:

void func(const parent* ptr) 
{ 
    // actions... 
} 
func(*childptr); 

Вот хорошая статья о смарт-указатели и передачи его функций: http://herbsutter.com/2013/06/05/gotw-91-solution-smart-pointer-parameters.

2

Ничего особенного не требуется из-за наследования. Вы должны использовать std::move передать unique_ptr к функции, но это правда, даже если типы совпадают:

#include <memory> 

struct A { 
}; 

struct B : A { 
}; 

static void f(std::unique_ptr<A>) 
{ 
} 

int main(int,char**) 
{ 
    std::unique_ptr<B> b_ptr(new B); 
    f(std::move(b_ptr)); 
} 
Смежные вопросы