boost :: shared_ptr me dérange vraiment. Certes, je comprends l'utilité d'une telle chose, mais je souhaite que je pourrais utiliser le shared_ptr<A>
comme un A*
. Considérez le code suivantC++: Créer un objet partagé plutôt qu'un pointeur partagé vers un objet
class A
{
public:
A() {}
A(int x) {mX = x;}
virtual void setX(int x) {mX = x;}
virtual int getX() const {return mX;}
private:
int mX;
};
class HelpfulContainer
{
public:
//Don't worry, I'll manager the memory from here.
void eventHorizon(A*& a)
{
cout << "It's too late to save it now!" << endl;
delete a;
a = NULL;
}
};
int main()
{
HelpfulContainer helpfulContainer;
A* a1 = new A(1);
A* a2 = new A(*a1);
cout << "*a1 = " << *a1 << endl;
cout << "*a2 = " << *a2 << endl;
a2->setX(2);
cout << "*a1 = " << *a1 << endl;
cout << "*a2 = " << *a2 << endl;
cout << "Demonstrated here a2 is not connected to a1." << endl;
//hey, I wonder what this event horizon function is.
helpfulContainer.eventHorizon(a1);
cout << "*a1 = " << *a1 << endl;//Bad things happen when running this line.
}
Celui qui a créé le HelpfulContainer ne pensait pas à d'autres qui souhaitent conserver des pointeurs vers des objets A. Nous ne pouvons pas donner d'objets helpfulClass boost :: shared_ptr. Mais une chose que nous pourrions faire est d'utiliser l'idiome pimlp pour créer une SharedA qui est lui-même un A:
class SharedA : public A
{
public:
SharedA(A* a) : mImpl(a){}
virtual void setX(int x) {mImpl->setX(x);}
virtual int getX() const {return mImpl->getX();}
private:
boost::shared_ptr<A> mImpl;
};
Et la fonction principale peut ressembler à ceci:
int main()
{
HelpfulContainer helpfulContainer;
A* sa1 = new SharedA(new A(1));
A* sa2 = new SharedA(sa1);
cout << "*sa1 = " << *sa1 << endl;
cout << "*sa2 = " << *sa2 << endl;
sa2->setX(2);
cout << "*sa1 = " << *sa1 << endl;
cout << "*sa2 = " << *sa2 << endl;
cout << "this demonstrates that sa2 is a shared version of sa1" << endl;
helpfulContainer.eventHorizon(sa1);
sa2->setX(3);
//cout << "*sa1 = " << *sa1 << endl;//Bad things would happen here
cout << "*sa2 = " << *sa2 << endl;
//but this line indicates that the originally created A is still safe and intact.
//only when we call sa2 goes out of scope will the A be deleted.
}
Alors, mon question est la suivante: Est-ce que le motif ci-dessus est un bon motif, ou y at-il quelque chose que je ne considère pas encore. Mon projet actuel a hérité d'une classe HelpfulContainer
comme ci-dessus qui supprime les pointeurs dont j'ai besoin, mais j'ai toujours besoin de la structure de données présente dans le HelpfulContainer.
Mise à jour: Cette question est une question subséquente.
Si HelpfulContainer veut prendre en charge le pointeur, il doit utiliser la sémantique correcte pour le faire. L'interface 'eventHorizon' est mal nommée car elle n'explique pas ce qui se passe et le paramètre qu'elle doit indiquer devrait indiquer que la propriété est transférée (disons std :: auto_ptr ou son nouveau remplacement std :: unique_ptr). Ces deux éléments indiquent que l'objet HelpfullContainer prend possession de l'objet et qu'il ne sera plus valide après l'appel. Donc, vous prouvez le point que dans le code C++ peut être mal écrit par des gens qui ne comprennent pas la sémantique du langage. –