Voir le titre.
J'ai:
class Foo {
private:
Foo();
public:
static Foo* create();
}
Que dois-je faire d'ici pour que Foo ne puisse plus être copié?
Merci!
Voir le titre.
J'ai:
class Foo {
private:
Foo();
public:
static Foo* create();
}
Que dois-je faire d'ici pour que Foo ne puisse plus être copié?
Merci!
class Foo {
private:
Foo();
Foo( const Foo& other ); // non construction-copyable
Foo& operator=( const Foo& ); // non copyable
public:
static Foo* create();
}
Si vous utilisez boost, vous pouvez également hériter de noncopyable: http://www.boost.org/doc/libs/1_41_0/boost/noncopyable.hpp
EDIT: version C ++11 si vous avez un compilateur prenant en charge cette fonctionnalité:
class Foo {
private:
Foo();
Foo( const Foo& other ) = delete; // non construction-copyable
Foo& operator=( const Foo& ) = delete; // non copyable
public:
static Foo* create();
}
Un autre moyen d’interdire le constructeur de copie. Par commodité, une macro DISALLOW_COPY_AND_ASSIGN peut être utilisée:
// A macro to disallow the copy constructor and operator= functions
// This should be used in the private: declarations for a class
#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
TypeName(const TypeName&); \
void operator=(const TypeName&)
Ensuite, en classe Foo:
class Foo {
public:
Foo(int f);
~Foo();
private:
DISALLOW_COPY_AND_ASSIGN(Foo);
};
Pour ajouter un peu là.
La solution traditionnelle est, comme il a été dit, de déclarer à la fois Copy Constructor
et Assignment Operator
comme private
, et pas à définir .
private
, cela conduira à une erreur de compilation de quelqu'un d'essayer de les utiliser qui n'a pas accès à la partie privée de la classe...undefined symbol
, soit à un lien en temps (si vous vérifiez pour ceux-là) ou plus probablement au moment de l'exécution (quand vous essayez de charger la bibliothèque).Bien sûr, il est assez gênant dans le second cas, parce que vous devez ensuite vérifier votre code par vous-même puisque vous n'avez pas l'indication du fichier et la ligne à laquelle l'erreur se produit. Heureusement, elle est limitée à vos méthodes de classe et amis.
Aussi, il est intéressant de noter que ces propriétés sont transitive en bas de l'héritage et la composition de la route: le compilateur ne génère par défaut des versions de l' Default Constructor
, Copy Constructor
, Assignment Operator
et de la Destructor
si elle peut.
Cela signifie que pour un de ces quatre, ils sont générés automatiquement et seulement si ils sont accessibles pour toutes les bases et les attributs de la classe.
// What does boost::noncopyable looks like >
class Uncopyable
{
Uncopyable(const Uncopyable&);
Uncopyable& operator(const Uncopyable&);
};
C'est pourquoi, héritant de cette classe (ou en l'utilisant comme un attribut) empêche efficacement votre propre classe pour être copiable ou cessibles, sauf si vous définissez ces opérateurs vous-même.
Généralement, l'héritage est choisi sur la composition là pour 2 raisons:
Uncopyable
, même si le polymorphisme ne peut être qu'utileEBO
ou Empty Base Optimization
, tandis qu'un attribut est adressable et ainsi occupera de la mémoire (dans chaque instance de la classe), même si elle n'a pas besoin de l'utiliser, le compilateur a la possibilité de ne pas ajouter cette surcharge de travail pour une classe de base.Vous pouvez, sinon, déclarer les opérateurs privés et de ne pas les définir dans votre propre classe, mais le code sera moins auto-documentation, et vous ne serait pas en mesure de rechercher automatiquement pour ceux de la classe qui ont cette propriété, alors (sauf si vous avez un véritable analyseur).
Espérons que cela de jeter un peu de lumière sur le mécanisme.
Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.