Как бороться с неудачным конструктором, когда исключение не разрешено - PullRequest
2 голосов
/ 28 июля 2010

Я просматривал руководство по стилю Google C ++, и они решили не использовать исключения в коде C ++ , полагаясь на возвращаемые значения.

Мой вопрос: как вы обрабатываете ошибки в конструкторах в этом случае, поскольку вы не можете возвращать значения в них.

Спасибо!

Ответы [ 6 ]

7 голосов
/ 28 июля 2010

Моим первым инстинктом было бы извлечь точку отказа из конструктора и создать метод инициализации.

Таким образом, вы можете создать свой объект, не опасаясь сбоя, а затем вызвать функцию init ().Эта функция может возвращать что-то вроде int для успеха / неудачи, например -1, если происходит сбой.

Да, это дополнительный шаг, но он поможет вам избежать возможности провалить конструктор

4 голосов
/ 28 июля 2010

Это довольно уродливо, но способ сделать это состоит в том, чтобы зарезервировать «особое состояние» объекта, чтобы оно означало «строительство не удалось».Затем вы должны запросить это состояние.Тьфу!

2 голосов
/ 28 июля 2010

Я новичок в C ++, так что мое мнение не стоит так много; но я столкнулся по крайней мере с несколькими разными подходами.

В одной библиотеке, которую я недавно использовал, каждый конструктор имеет аргумент int&, который возвращает статус конструкции; документация для этой библиотеки гласит, что она вызовет неопределенное поведение, если результат построения недопустим. При таком подходе вызывающая сторона несет ответственность за то, чтобы не использовать недопустимый класс.

TheClass::TheClass(int &result)
{
    result = -1; // or some error value
    // do lots of initialisation
    result = 0; // success
}

У другого, который я видел, был метод is_valid(). Если конструкция не удалась, переменная логического члена была установлена ​​в false и возвращалась из этого метода is_valid() (этот метод также проверял несколько других вещей). Мне удалось увидеть источник этого и найти каждую функцию-член, начинающуюся с оператора if(is_valid()). Не могу сказать, что я фанат этого подхода.

TheClass::TheClass() : m_valid(false)
{
    // do the initialisation
    if (everything_ok)
        m_valid = true;
}

void TheClass::method()
{
    if (!is_valid()) return;
    // do some work
}

Однако недавно я читал, что исключения не такие медленные и грязные, как раньше, и их можно элегантно реализовать. Google может запретить их по любой причине, но они все еще являются частью языка C ++. С тем же успехом вы можете работать с предоставленными вам инструментами, чем строить дом с помощью только отвертки.

2 голосов
/ 28 июля 2010

Вы можете сделать следующее:

class X;
class Y;

class Foo
{
   public:
      //! This function validates the input, and returns an error status if
      //! the Foo can not be created. Otherwise we return a successful status
      //! and output points to a newly constructed Foo. The Foo constructor 
      //! is only called once the inputs are validated.
      //! No exceptions are thrown.
      static Status buildInstance(X const& x, Y const& y, std::auto_ptr<Foo>& output);

   private:
      Foo(X const& x, Y const& y);
};

В прошлом я часто использовал этот шаблон (потому что должен был), но, тем не менее, я предпочитаю, чтобы мои конструкторы создавали исключения. Вышесказанное в лучшем случае не элегантно, а в худшем довольно громоздко.

2 голосов
/ 28 июля 2010

Они в основном ничего не делают в своих конструкторах.

Также из Руководства по стилю Google C ++: Работа в Конструкторах ссылка ▶ В общем, конструкторы должны просто установить переменные-члены в их начальные значения. Любая сложная инициализация должна идти в явном методе Init ().

1 голос
/ 28 июля 2010

Вы можете установить поле класса / объекта, чтобы проверить, не возникла ли ошибка.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...