2017-05-28 6 views
0

J'ai des difficultés à essayer de trouver une solution qui me permettra de garder la portée d'un objet local à une méthode principale tout en attrapant une exception d'initialisation potentielle.Essayer de déterminer la portée de l'initialisation de la variable de classe

Le pseudo-code ci-dessous essaie de mieux illustrer mon problème.

int main() { 
    // Initialisation 
    SomeObject * object; 

    try { 
     SomeObject obj; // Initialisation can cause an exception 
     object = &obj; 
    } 
    catch (SomeException &ex) { 
     // Handle exception 
    } 

    // object out of scope undefined behaviour 

    // Application Logic 
    return 0; 
} 

Je comprends que l'objet sera supprimé une fois que les extrémités du bloc try et donc le pointeur lorsqu'il est utilisé conduira à un comportement non défini.

Comment puis-je faire quelque chose comme ceci et passer l'objet à la portée de la fonction afin que l'objet ne soit pas supprimé?

Je peux utiliser une solution C++ 14 dans mon projet.

+0

méthode' - pourquoi dans ce cas et pas dec Lare-le dans la portée où vous voulez l'utiliser? Si vous déclarez un objet en tant que variable locale dans la sous-fonction - il sera de toute façon détruit après que vous ayez quitté cette sous-fonction pour 'main'. donc si vous avez besoin d'un objet dans la portée 'main' - déclarez-le ici – RbMm

Répondre

1

Comment puis-je faire quelque chose comme ceci et passer l'objet à la portée de la fonction afin que l'objet ne soit pas supprimé?

Vous pouvez utiliser un pointeur intelligent à la place:

int main() { 
    // Initialisation 
    std::unique_ptr<SomeObject> object; 

    try { 
     object = std::make_unique<SomeObject>(); // Initialisation can cause an exception 
    } 
    catch (SomeException &ex) { 
     // Handle exception 
    } 

    if(object) { 
     // Application Logic 
    } 
    return 0; 
} 
+0

Merci, je crois que c'est ce dont j'avais besoin. –

0

La façon évidente serait le « bloc try fonction »

int main() try 
{ 
    SomeObject object; 

    // Application logic - able to use object 

    return 0; 
} 
catch (SomeException &ex) 
{ 
    // Handle exception 
} 

Cela permet au gestionnaire d'exceptions pour nettoyer avant la fin du programme .

Si vous voulez que le gestionnaire d'exceptions au sein main(), puis une option est

int main() 
{ 
     try 
     { 
      SomeObject object; 

      // Application logic able to use object 
     }  
     catch (SomeException &ex) 
     { 
      // Handle exception 
     } 
} 

Avec des structures de contrôle appropriées (par exemple, l'ensemble try/catch dans une boucle), il est possible pour le bloc catch pour récupérer de la erreur, et recommencez.

Si vous voulez vraiment que la définition de l'objet et l'initialisation soient séparées, vous pouvez faire quelque chose comme (C++ 11 et ultérieur);

#include <memory> 
int main() 
{ 
    std::unique_ptr<SomeObject> object; 

    try 
    { 
      object = std::make_unique<SomeObject>(); 
    } 
    catch (SomeException &ex) 
    { 
     // Handle exception 
    } 

    // code here cannot assume construction of object succeeded 

    if (object) 
    { 
     // Application Logic can assume object is properly constructed 
    } 
    return 0; 
} 

Avant le 11 C++, le ci-dessus peuvent utiliser std::auto_ptr (qui a été dépréciée en C++ 11 en faveur de unique_ptr.

Le choix approprié dépend si vous voulez que la « logique de l'application » à supposerobject a été correctement construit (c'est-à-dire que la logique d'application n'est jamais exécutée jusqu'à ce que la construction de l'objet réussisse) ou si elle doit tester la possibilité d'une défaillance