#c #smart-pointers
#c #интеллектуальные указатели
Вопрос:
Рассмотрим следующие базовые и производные классы.
class base
{
public:
int i{9};
virtual void func()
{
cout << "base" << endl;
}
virtual ~base()
{
}
};
class derived : public base
{
public:
int i{4};
void func()
{
cout << "derived" << endl;
}
};
Я хотел бы создать unique_ptr
тип base
для derived
объекта. Я знаю, что могу сделать
std::unique_ptr<base> ptr{new derived};
но когда я делаю
auto ptr = std::make_unique<base>(derived{});
ptr->func();
это выводит base
, что не является моим предполагаемым поведением. Какой правильный способ использовать std::make_unique
в этом случае? Кроме того, почему auto ptr = std::make_unique<base>(derived{})
делает?
Ответ №1:
Когда вы делаете
auto ptr = std::make_unique<base>(derived{});
make_unique<base>
собирается создать unique_ptr<base>
что означает, что он собирается создать только base
объект. Поскольку derived
является производным от base, законно передавать это в base
конструктор копирования, чтобы код компилировался, но у вас есть base
, а не derived
.
Что вам нужно, так это
std::unique_ptr<base> ptr = std::make_unique<derived>();
чтобы получить base
указатель, который указывает на derived
объект. Это не тот синтаксис, который вам нужен, но он работает правильно.
Если вы использовали
auto ptr = std::make_unique<derived>();
тогда ptr
было бы std::unique_ptr<derived>
, а не std::unique_ptr<base>
.
Комментарии:
1. Ах, я понимаю. В
auto ptr = std::make_unique<base>(derived{});
я думал, что временноеderived{}
сообщение будет перенаправлено вunique_ptr
конструктор. Это не тот случай, иначе эта строка сделала бы то, что я хотел, чтобы она делала?2. @roulette01 Он пересылается конструктору, просто, поскольку вы использовали
std::make_unique<base>
, он будет смотреть только наbase
конструкторы для созданияbase
объекта. Поскольку онderived
является производным отbase
, он может вызыватьbase
конструкторbase(const baseamp;)
,, который компилятор неявно сгенерировал. Это разбивает производный объект только на базовую часть.