Atualmente, estou tentando aprender como usar ponteiros inteligentes. No entanto, ao fazer alguns experimentos, descobri a seguinte situação para a qual não consegui encontrar uma solução satisfatória:
Imagine que você tenha um objeto da classe A sendo pai de um objeto da classe B (o filho), mas ambos deveriam se conhecer:
class A;
class B;
class A
{
public:
void addChild(std::shared_ptr<B> child)
{
children->push_back(child);
// How to do pass the pointer correctly?
// child->setParent(this); // wrong
// ^^^^
}
private:
std::list<std::shared_ptr<B>> children;
};
class B
{
public:
setParent(std::shared_ptr<A> parent)
{
this->parent = parent;
};
private:
std::shared_ptr<A> parent;
};
A questão é como um objeto da classe A pode passar um std::shared_ptr
de si mesmo ( this
) para seu filho?
Existem soluções para ponteiros compartilhados do Boost ( Obtendo um boost::shared_ptr
parathis
), mas como lidar com isso usando std::
ponteiros inteligentes?
c++
this
shared-ptr
this-pointer
Icaro
fonte
fonte
Respostas:
Existe
std::enable_shared_from_this
apenas para esse efeito. Você herda dele e pode chamar.shared_from_this()
de dentro da classe. Além disso, você está criando dependências circulares que podem levar a vazamentos de recursos. Isso pode ser resolvido com o uso destd::weak_ptr
. Portanto, seu código pode ser assim (assumindo que os filhos dependem da existência do pai e não o contrário):Observe, entretanto, que a chamada
.shared_from_this()
requer quethis
seja propriedade destd::shared_ptr
no ponto de chamada. Isso significa que você não pode mais criar tal objeto na pilha e geralmente não pode chamar.shared_from_this()
de dentro de um construtor ou destruidor.fonte
shared_ptr
baseado em um padrão construídoshared_ptr
e o que você quiser apontar para ...shared_ptr
são irrelevantes para esta questão.shared_from_this
As pré-condições de afirmam claramente que o objeto deve pertencer (não apenas ser apontado) por algunsshared_ptr
no momento da chamada.shared_ptr
é exigida no momento da chamada, mas em um padrão de uso típico, ou seja, algo comoshared_ptr<Foo> p(new Foo());
,shared_ptr
assume a propriedade do objeto somente após ele ser totalmente construído. É possível contornar isso criandoshared_ptr
no construtor inicializado comthis
e armazenando-o em algum lugar não local (por exemplo, em um argumento de referência) para que não morra quando o construtor for concluído. Mas é improvável que esse cenário complicado seja necessário.Você tem vários problemas em seu design, que parecem resultar de sua compreensão equivocada de ponteiros inteligentes.
Ponteiros inteligentes são usados para declarar propriedade. Você está quebrando isso ao declarar que ambos os pais são donos de todos os filhos, mas também que cada filho possui seus pais. Ambos não podem ser verdade.
Além disso, você está retornando um indicador fraco em
getChild()
. Ao fazer isso, você está declarando que o chamador não deve se preocupar com a propriedade. Agora, isso pode ser muito limitante, mas também ao fazer isso, você deve se certificar de que a criança em questão não será destruída enquanto quaisquer ponteiros fracos ainda estiverem sendo pressionados, se você usasse um ponteiro inteligente, ele seria resolvido por si mesmo .E a coisa final. Normalmente, quando você está aceitando novas entidades, normalmente deve aceitar ponteiros brutos. O ponteiro inteligente pode ter seu próprio significado para trocar filhos entre pais, mas para uso geral, você deve aceitar ponteiros brutos.
fonte