У меня возникают трудности при попытке найти решение, которое позволит мне сохранять область действия объекта локальной для метода main, перехватывая при этом потенциальное исключение инициализации.

Псевдокод ниже пытается лучше всего проиллюстрировать мою проблему.

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;
}

Я понимаю, что объект будет удален после окончания блока try, поэтому указатель при использовании приведет к неопределенному поведению.

Как я могу сделать что-то подобное и передать объект в область действия функции, чтобы объект не был удален?

Я могу использовать решение C ++ 14 в моем проекте.

1
a_dizzle 28 Май 2017 в 03:22

2 ответа

Лучший ответ

Как я могу сделать что-то подобное и передать объект в область действия функции, чтобы объект не был удален?

Вместо этого вы можете использовать умный указатель:

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;
}
2
πάντα ῥεῖ 28 Май 2017 в 00:31

Очевидным способом было бы «блокирование функции»

int main() try
{
     SomeObject object;

     // Application logic - able to use object

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

Это позволяет очищать обработчик исключений перед завершением программы.

Если вы хотите обработчик исключений в main(), то один из вариантов

 int main()
 {
      try
      {
           SomeObject object;

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

При наличии соответствующих управляющих структур (например, всего try / catch в цикле) блок catch может восстановиться после ошибки и возобновить работу.

Если вы действительно хотите, чтобы определение объекта и инициализация были разделены, вы можете сделать что-то вроде (C ++ 11 и более поздние версии);

#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;
}

До C ++ 11 вышеприведенное может использовать std::auto_ptr (что устарело в C ++ 11 в пользу unique_ptr.

Подходящий выбор зависит от того, хотите ли вы, чтобы «логика приложения» могла предполагать, что object была правильно построена (т. Е. Логика приложения никогда не выполняется до тех пор, пока не будет успешно завершено построение объекта) или если она необходимо проверить на возможность отказа.

1
Peter 28 Май 2017 в 08:54