Есть ли случаи, где “наконец” конструкция была бы полезна в C++?

Существует свойство с именем LogicalChildrenInternal, которое отвечает за перечисление дочерних элементов каждого элемента. К сожалению, он является внутренним виртуальным и возвращает статическую пустую коллекцию, поэтому класс Element не подходит для прямого использования. В таких классах, как ViewCell и Layout, где это свойство переопределяется, вы можете заменить исходную коллекцию с помощью отражения и увидеть, что новый набор дочерних элементов отображается в макете.

6
задан jalf 23 December 2008 в 04:24
поделиться

5 ответов

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

Сравните:

class RAII_Wrapper
{
    Resource *resource;

public:
    RAII_Wrapper() : resource(aquire_resource()) {}

    ~RAII_Wrapper() {
        free_resource(resource);
        delete resource;
    }

    Resource *getResource() const {
        return resource;
    }
};

void Process()
{
    RAII_Resource wrapper;
    do_something(wrapper.resource);
}

по сравнению с:

void Process()
{
    try {
        Resource *resource = aquire_resource();
        do_something(resource);
    }
    finally {
        free_resource(resource);
        delete resource;
    }
}

Большинство людей (включая меня) все еще утверждало бы, что первая версия лучше, потому что она не вынуждает Вас использовать попытку... наконец блок. Также только необходимо записать класс однажды, не копировать код в каждой функции, которая использует ресурс.

Править: Как упомянутый litb, необходимо использовать auto_ptr вместо того, чтобы удалить указатели вручную, которые упростили бы оба случая.

6
ответ дан 8 December 2019 в 05:24
поделиться

Наконец было бы лучше при соединении с кодом C. Это может быть боль для обертывания существующей функциональности C в RAII.

6
ответ дан 8 December 2019 в 05:24
поделиться

Различие между ними - то, что деструкторы подчеркивают повторное использование решения для очистки путем соединения его с используемым типом, тогда как попытка/наконец подчеркивает одноразовые стандартные программы очистки. Таким образом, попытка/наконец более сразу удобна, когда у Вас есть уникальное одноразовое требование очистки, связанное с точкой использования, а не допускающим повторное использование решением для очистки, которое может быть связано с типом, который Вы используете.

Я не попробовал это (не загрузили недавний gcc в течение многих месяцев), но это должно быть верно: с добавлением лямбд на язык C++ может теперь иметь эффективный эквивалент finally, только путем записи вызванной функции try_finally. Очевидное использование:

try_finally([]
{
    // attempt to do things in here, perhaps throwing...
},
[]
{
    // this always runs, even if the above block throws...
}

Конечно, необходимо записать try_finally, но только однажды и затем Вы хороши для движения. Лямбды включают новые управляющие структуры.

Что-то как:

template <class TTry, class TFinally>
void try_finally(const TTry &tr, const TFinally &fi)
{
    try
    {
        tr();
    }
    catch (...)
    {
        fi();
        throw;
    }

    fi();
}

И нет никакой ссылки вообще между присутствием GC и предпочтением попытки/наконец вместо деструкторов. C++ / CLI имеет деструкторы и GC. Они - ортогональный выбор. Попытка/наконец и деструкторы являются немного отличающимися решениями той же проблемы, оба детерминированные, необходимые для невзаимозаменяемых ресурсов.

Функциональные объекты C++ подчеркивают возможность многократного использования, но делают одноразовые анонимные функции болезненными. Путем добавления лямбд анонимные блоки кода теперь легко сделать, и это избегает традиционного акцента C++ на "принудительную возможность многократного использования", выраженную через именованные типы.

7
ответ дан 8 December 2019 в 05:24
поделиться

Редактирование после шести ответов.

Что относительно этого:

class Exception : public Exception { public: virtual bool isException() { return true; } };
class NoException : public Exception { public: bool isException() { return false; } };


Object *myObject = 0;

try
{
  try
  {
    myObject = new Object(); // Create an object (Might throw exception)
  }
  catch (Exception &e)
  {
    // Do something with exception (Might throw if unhandled)
  }

  throw NoException();
}
catch (Exception &e)
{
  delete myObject;

  if (e.isException()) throw e;
}
0
ответ дан 8 December 2019 в 05:24
поделиться

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

3
ответ дан 8 December 2019 в 05:24
поделиться
Другие вопросы по тегам:

Похожие вопросы: