Я пытаюсь передать право собственности на уже определенный std::unique_ptr
члену объекта класса:
#include <iostream>
#include "memory"
// base class
class base
{
public:
void setVal(int val)
{
m_val = val;
}
int getVal()
{
std::cout << "base val = " <<m_val<<std::endl;
return m_val;
}
private:
int m_val = 0;
};
// derived class
class derived1: public base
{
private:
};
// derived class
class derived2: public base
{
public:
private:
};
class user
{
public:
user(std::unique_ptr<base> d)
{
// m_class = static_cast<std::unique_ptr<base>>(d.get());
// m_class = std::make_unique<base>();
m_class = std::move(d);
}
user(std::unique_ptr<derived1> d)
{
// m_class = static_cast<std::unique_ptr<derived1>>(d.get());
// m_class = std::make_unique<derived2>();
m_class = std::move(d);
}
user(std::unique_ptr<derived2> d)
{
// m_class = static_cast<std::unique_ptr<derived2>>(d.get());
// m_class = std::make_unique<derived2>();
m_class = std::move(d);
}
void setVal(int val)
{
m_class->setVal(val);
}
int getVal()
{
return m_class->getVal();
}
private:
std::unique_ptr<base> m_class;
};
int main()
{
std::unique_ptr<base> b = std::make_unique<base>();
std::unique_ptr<base> d1 = std::make_unique<derived1>();
std::unique_ptr<base> d2 = std::make_unique<derived2>();
user ud1(std::move(d1));
user ud2(std::move(d2));
ud2.setVal(90);
ud1.setVal(10);
ud2.getVal();
ud1.getVal();
return 0;
}
Кажется, я дважды нажал указатель; впервые передаем std::move
std::unique_ptr
и d1
конструктору объекта d2
; во второй раз это user
std::move
или d1
в переменную-член d2
.
Дважды m_class
указатель не кажется интуитивно понятным, чтобы в конечном итоге передать право владения std::move
и d1
m_class. Правильно ли я делаю, или есть правильный/лучший способ сделать это? Спасибо!!
Правильно ли я делаю, или есть правильный/лучший способ сделать это?
Правильно переместить его дважды, поскольку вы переносите значение между тремя разными переменными.
Это тоже не проблема. std::move
— это приведение во время компиляции. Вызов его дважды не влияет на производительность.
Однако...
Вам следует использовать списки инициализаторов участников.
user(std::unique_ptr<base> d)
: m_class{ std::move(d) }
{
}
И эти конструкторы лишние. Удалите их. Вам не нужно учитывать все возможные производные типы, все они могут неявно конвертироваться в std::unique_ptr<base>
.
user(std::unique_ptr<derived1> d)
{
// m_class = static_cast<std::unique_ptr<derived1>>(d.get());
// m_class = std::make_unique<derived2>();
m_class = std::move(d);
}
user(std::unique_ptr<derived2> d)
{
// m_class = static_cast<std::unique_ptr<derived2>>(d.get());
// m_class = std::make_unique<derived2>();
m_class = std::move(d);
}
Спасибо !!@Дрю Дорманн
@NickXTsui нет, член всегда останется тем классом, в котором он был создан (именно поэтому необходимы виртуальные деструкторы), но вы все равно всегда сохраняете его как std::unique_ptr<base> m_class;
, поэтому дополнительные конструкторы не нужны.
Спасибо @SirNate!!
Единственная проблема заключается в том, что если конструктор получит точку как базовый класс, станет ли член в конечном итоге базовым классом, а не производным?