8
votes

C ++, empêchant l'instance de classe d'être créée sur la pile (pendant la compilation)

Je sais qu'il existe des méthodes pour empêcher une classe d'être créée sur le tas, en empêchant l'utilisateur d'utiliser le Nouveau et Supprimer Opérateur. J'essaie de faire exactement le contraire. J'ai une classe que je souhaite empêcher l'utilisateur de la créer une instance sur la pile et que seules les instances instiguées à l'aide de l'opérateur nouveau compileront. Plus spécifiquement, je souhaite que le code suivant reçoive une erreur lors de la compilation: xxx

de la recherche sur le Web, j'ai trouvé cette suggestion sur la façon de le faire: xxx < / Pré>

Ce que je ne comprends pas, c'est pourquoi cela devrait fonctionner. Pourquoi le destructeur serait-il appelé tout en créant une instance de myClass ?


3 commentaires

A la façon dont appeler destrory () comme cela vous donnera une erreur de compilateur aussi bien que cela est déclaré privé


Je serais intéressé de savoir pourquoi tu veux ça?


Consultez mon autre question, qui l'explique à fond: Stackoverflow.com/Questtions/3095856/...


5 Réponses :


12
votes

Pourquoi le destructeur serait-il appelé tout en créant une instance de myClass code>? p>

Ce n'est pas le cas. Il doit être invoqué automatiquement lorsque l'instance dépasse de la portée. Si c'est privé, le compilateur ne doit pas générer ce code, d'où l'erreur. P>

Si vous pensez que le destructeur privé est obscur, une autre façon de restreindre une classe à une allocation dynamique est de rendre tous les constructeurs privés et que des myClass :: créer () code> fonctions Retour des objets alloués dynamiquement: P>

class MyClass {
public:
  static std::shared_ptr<MyClass> create()             {return new MyClass();}
  static std::shared_ptr<MyClass> create(const Foo& f) {return new MyClass(f);}
  // ...
};


9 commentaires

-1 pour "Si c'est privé, le compilateur ne doit pas générer ce code, ..."


Si c'est privé, cela ne peut être appelé à partir de la classe d'intérieur uniquement. Cela ne signifie pas que le compilateur doit ou ne doit pas générer de code.


@Berkus: la confidentialité n'est qu'une caractéristique du front de compilateur. Rien que la règle ne soit encodée à ne pas laisser l'accès empêcherait un compilateur de générer du code pour accéder aux données privées. Vous pouvez voir cela lorsque vous #define privé public avant d'inclure une classe que vous avez uniquement en tant que fichiers d'objets (dans une lib, généralement): tout en invoquant techniquement comportement non défini, la plupart des compilateurs généreront avec heureusement que le code a accès à l'accès. données privées dans cette classe. Techniquement, ce n'est pas un problème, alors Les seuls compilateurs de la raison ne permettent pas d'accéder aux privés est parce qu'ils ne doivent pas .


@Berkus: "Si cela est déclaré privé, le compilateur ne doit pas générer ce code." est absolument correct, bien que sur-spécifique. Mieux reviendrait, "si cela est déclaré, le compilateur ne doit pas générer ce code, le programmeur revendique le privilège de l'écrire lui-même." C ++ 0x corrige cela avec des fonctions de membre par défaut.


Merci SBI. Nous utilisons des pointeurs intelligents pour tous nos objets partagés, mais il convient certainement de noter.


EHM, nous avons une sorte de malentendu textuel ici. Puisque l'anglais n'est pas ma langue naturelle, je ne plongerai pas dans ce débat.


@Berkus: Dans ma langue "Tu ne dois pas" signifierait "tu n'as pas à". En anglais, cependant, cela signifie «vous n'êtes pas autorisé à». Cela pourrait-il être la racine de la confusion?


@SBI: concernant "ne doit pas" "- exactement bien. Quand j'ai appris l'allemand (en tant qu'infrican anglais natif), savoir quand utiliser Duerfen contre Muessen dans le négatif, il m'a fallu un moment pour le faire bien. Bravo à vous et Berkus pour avoir conversé dans une langue non native.


@sbi je crois que c'est la racine de ma confusion. Désolé pour ça!



1
votes

Parce que lorsque l'instance sort de la portée, elle doit être déstructurée à l'aide du destructeur. Le pointeur en instance ne fait pas cela.


0 commentaires

25
votes

Lorsque myClass code> atteint la fin de sa portée (le prochain } code>) Le compilateur appelle le destructeur pour libérer de la pile. Si le destructeur est privé, cependant, le destructeur n'est pas accessible, la classe ne peut donc pas être placée sur la pile.

Je n'aime pas le look de Supprimer ce code>. En général, je pense que les objets ne doivent pas se détruire. Peut-être une meilleure façon est d'avoir un constructeur privé em> pour votre classe, puis utilisez une fonction statique pour créer une instance. P>

// In class declaration...
static MyClass* Create()
{
    return new MyClass(); // can access private constructor
}

// ...

MyClass myclass; // illegal, cannot access private constructor

MyClass* pMyClass = MyClass::Create();
delete pMyClass; // after usage


6 commentaires

+1 - Au lieu de jouer avec des destructeurs privés à l'aide d'une variation du motif singleton est la voie à suivre


@Holger: Le seul et unique but d'un singleton est de permettre une seule instance , et cela ne fait pas cela, alors Ce n'est pas un singleton du tout. < I> J'aimerais pouvoir voter - voter des commentaires.


+1 Bon, en utilisant une méthode d'usine au lieu de pirater quelque chose qui pourrait ne pas être aussi évident pour une personne qui doit utiliser votre code.


+1 jouera mieux avec la plupart des pointeurs automatiques que l'original.


@sbi: J'aimerais pouvoir le faire aussi.


bon. Cela vient certainement plus naturellement à l'utilisateur qui doit utiliser cette classe. Merci pour l'explication sur la raison pour laquelle l'approche DTOR privée fonctionnerait aussi



1
votes

Chaque fois qu'une variable locale est hors de portée, elle est détruite. Et sur la destruction, destructeurs de l'objet sont appelés. Ici, la portée est de la fonction principale. Lorsque le programme quitte, le destructeur de MyClass Object sera appelé


0 commentaires

1
votes

Ce n'est pas le cas. Le compilateur tente d'appeler le destructeur lorsqu'il sort hors de portée et indique à la ligne de code qui produit cet effet, qui est beaucoup plus utile que de pointer à la fin de la fonction.


4 commentaires

Cela devrait être un commentaire (vous ne répondez pas du tout à la question (principale)). Idem pour le packeep ci-dessus.


La question était "Pourquoi le destructeur serait-il appelé tout en créant une instance de myclass?". C'est une réponse à cette question. Apprenez à lire en premier.


@Berkus hein? La question dans le titre est "C ++, la prévention de la classe de classe d'être créée sur la pile (pendant la compilation)". Désolé mais cela ne répond pas à cette question.


Le titre de la question n'est pas la question elle-même. La question est une phrase ou un paragraphe qui se termine par un signe de question.