Как использовать метод get для возврата закрытого члена класса std::unique_ptr

Я создал класс с членами private, std::unique_ptr, а именно, m_VBO и m_EBO, как показано.

class VAO {

public:
    VAO();
    std::unique_ptr<VBO> GetVBO();
    std::unique_ptr<EBO> GetEBO();

private:
    std::unique_ptr<VBO> m_VBO;
    std::unique_ptr<EBO> m_EBO;
};

Класс также включает методы get для защиты и возврата этих членов для использования при необходимости.

Определение этих методов "get" таково:

//*************************************************************************************************
std::unique_ptr<VBO> VAO::GetVBO()
{
    return std::make_unique<VBO>(m_VBO);
    //return std::make_unique<VBO>();
}

//*************************************************************************************************
std::unique_ptr<EBO> VAO::GetEBO()
{
    //return std::make_unique<EBO>(m_EBO);
    return std::make_unique<EBO>();
}

который не работает.

Я не могу понять правильную технику написания методов "получить".

Как это делается?


person user34299    schedule 04.09.2019    source источник
comment
Как это не работает?   -  person NathanOliver    schedule 04.09.2019
comment
Вероятно, ваша конструкция неверна. VAO является уникальным владельцем этого ресурса. Он не может совместно использовать объект снаружи, потому что это означало бы потерю уникального права собственности на объект. Можно либо (лучший вариант) реорганизовать свою логику так, чтобы не нужны были геттеры, (чуть хуже) передать объект вместе с владением или (неплохо, но хуже из этих трех) сделать указатель std::shared_ptr, чтобы он мог иметь много владельцы.   -  person Yksisarvinen    schedule 04.09.2019
comment
Другим вариантом было бы вернуть ссылку на указатель.   -  person super    schedule 04.09.2019
comment
Если вы даете кому-то что-то уникальное, у вас больше нет этой вещи. Вы должны дважды подумать, прежде чем делать это.   -  person n. 1.8e9-where's-my-share m.    schedule 04.09.2019
comment
Две мысли, что лучше? Во-первых, сделайте член m_VBO открытым членом класса VAO типа std::unique_ptr‹VBO› и исключите метод получения. Во-вторых, сделайте m_VBO закрытым членом класса VAO типа VBO с тем же методом получения, а затем создайте экземпляры VAO как указатель std::unique‹VAO›.   -  person user34299    schedule 06.09.2019


Ответы (3)


Уникальный указатель, как следует из названия, уникален. Так что клонировать нельзя! Вы можете только переместить его.

Итак, в основном в зависимости от ваших потребностей есть несколько разумных решений:

  1. Показать ссылку на объект (или необработанный указатель на объект):
VBO& VAO::GetVBO() const
{
    return *m_VBO;
}
  1. Передача права собственности:
std::unique_ptr<VBO> VAO::takeVBO()
{
    return std::move(m_VBO);
}
  1. Обеспечьте функциональность клонирования для VBO:
std::unique_ptr<VBO> VAO::clone() const
{
    return std::make_unique<VBO>(*m_VBO);
}
  1. Изменить std::unique_ptr на std::shared_ptr


Рекомендую посмотреть: Херба Саттера "Leak-Freedom в C++... по умолчанию".

person Marek R    schedule 04.09.2019
comment
Я посмотрю видео Херба Саттера. Спасибо. - person user34299; 06.09.2019

Если вы делитесь указателями с другими, вам необходимо учитывать, кто отвечает за время жизни объекта, на который он указывает.

Если может быть только одна сущность, отвечающая за всю жизнь, то std::unique_ptr — хороший выбор. Затем у вас есть возможность либо передать обязанности по управлению жизненным циклом кому-то другому, переместив уникальный_ptr. Или вы можете выдавать необработанные указатели, если вы знаете, что ваши клиенты являются только наблюдателями и не будут участвовать в управлении временем жизни (и тогда вам нужно убедиться, что объект, содержащий unique_ptr, переживет всех наблюдателей).

Если несколько сущностей должны иметь возможность по отдельности поддерживать объект в рабочем состоянии (совместное владение), то лучшим выбором будет std::shared_ptr.

person Jesper Juhl    schedule 04.09.2019

Ваша функция get должна выглядеть так

std::unique_ptr<VBO>& VBO::GetVBO()
{
    return m_VBO;
}
person Raj    schedule 04.09.2019
comment
это дерьмовое решение. Детализация реализации - person Marek R; 04.09.2019
comment
По крайней мере, сделать std::uniqe_ptr константой, нет? Все еще не очень хорошо, но, по крайней мере, предотвратит модификации. - person Jeffrey; 04.09.2019
comment
@Jeffrey: в то время как возврат std::unique_ptr<T>& может иметь смысл (поскольку вы действительно можете его изменить), возврат const std::unique_ptr<T>& бессмысленен. вместо этого лучше вернуть /* const */ T* (или ссылку, если не ноль). - person Jarod42; 04.09.2019