Заменив это:
self.__ui.tableView.clearSelection()
self.__ui.tableView.selectRow(previous.row())
этим:
QtCore.QTimer.singleShot(0.00001, lambda: self.__ui.tableView.selectRow(previous.row()))
дали желаемый результат
Стандартный ответ должен использовать некоторый вариант сокращенного RAII resource-allocation-is-initialization. В основном Вы создаете переменную, которая имеет тот же объем как блок, который был бы в блоке перед наконец, затем выполнил бы в работе наконец блок в деструкторе объектов.
try {
// Some work
}
finally {
// Cleanup code
}
становится
class Cleanup
{
public:
~Cleanup()
{
// Cleanup code
}
}
Cleanup cleanupObj;
// Some work.
Это выглядит ужасно неудобным, но обычно существует существующий ранее объект, который сделает уборку для Вас. В Вашем случае похоже, что Вы хотите разрушить объект в наконец блок, что означает, что умный или уникальный указатель сделает то, что Вы хотите:
std::unique_ptr<Object> obj(new Object());
или современный C++
auto obj = std::make_unique<Object>();
Неважно, какие исключения выдаются, объект будет разрушен. При возвращении к RAII в этом случае распределение ресурсов выделяет память для Объекта и создает его, и инициализация является инициализацией unique_ptr.
Нет. Стандартный способ создать наконец как путь состоит в том, чтобы разделить проблемы (http://en.wikipedia.org/wiki/Separation_of_concerns) и сделать объекты, которые используются в блоке попытки, автоматически высвобождают средства в их деструкторе (названный "Объем Связанное управление ресурсами"). Начиная с деструкторов, выполненных детерминировано, в отличие от этого, в Java, можно полагаться на них для чистки безопасно. Таким образом, объекты, что aquired ресурс также очистит ресурс.
Одним путем, который является особенным, является динамическое выделение памяти. Так как Вы - один aquiring ресурс, необходимо вымыться снова. Здесь, интеллектуальные указатели могут использоваться.
try {
// auto_ptr will release the memory safely upon an exception or normal
// flow out of the block. Notice we use the "const auto_ptr idiom".
// http://www.gotw.ca/publications/using_auto_ptr_effectively.htm
std::auto_ptr<A> const aptr(new A);
}
// catch...
Если по некоторой странной причине у Вас нет доступа к стандартным библиотекам, то очень легко реализовать столько же сколько Вы, потребность интеллектуального указателя вводит для обработки ресурса. Это может выглядеть немного подробным, но это - меньше кода, чем те вложенные блоки попытки/выгоды, и только необходимо определить этот шаблон однажды когда-либо, вместо однажды на ресурс, которому нужно управление:
template<typename T>
struct MyDeletable {
explicit MyDeletable(T *ptr) : ptr_(ptr) { }
~MyDeleteable() { delete ptr_; }
private:
T *ptr_;
MyDeletable(const MyDeletable &);
MyDeletable &operator=(const MyDeletable &);
};
void myfunction() {
// it's generally recommended that these two be done on one line.
// But it's possible to overdo that, and accidentally write
// exception-unsafe code if there are multiple parameters involved.
// So by all means make it a one-liner, but never forget that there are
// two distinct steps, and the second one must be nothrow.
Object *myObject = new Object();
MyDeletable<Object> deleter(myObject);
// do something with my object
return;
}
Конечно, если Вы будете делать это и затем будете использовать RAII в остальной части Вашего кода, то Вы в конечном счете закончите тем, что нуждались во всех функциях стандарта и повысите типы интеллектуального указателя. Но это - запуск и делает то, что я думаю, что Вы хотите.
Попытка... ловит подход, вероятно, не будет работать хорошо перед лицом эксплуатационного программирования. Блок УБОРКИ, как гарантируют, не будет выполнен: например, если "делают что-то", кодируют возвраты рано, или так или иначе бросает что-то, что не является Исключением. С другой стороны, деструктор "средства удаления" в моем коде, как гарантируют, будет выполнен в обоих тех случаях (хотя не, если программа завершится).
Мой совет: не пытайтесь эмулировать поведение попытки наконец пункт в C++. Просто используйте RAII вместо этого. Вы будете жить более счастливые.
Принятие Вас надеется удалять указатель myObject и избегать утечек памяти, Ваш код все еще может не сделать это, если существует оператор "возврата" в коде, где Вы говорите // Do something with myObject.
(Я предполагаю, что реальный код был бы здесь),
Методы RAII имеют соответствующее действие, которое эквивалентно "наконец" блок в деструкторе конкретного объекта:
class ResourceNeedingCleanup
{
private:
void cleanup(); // action to run at end
public:
ResourceNeedingCleanup( /*args here*/) {}
~ResourceNeedingCleanup() { cleanup(); }
void MethodThatMightThrowException();
};
typedef boost::shared_ptr<ResourceNeedingCleanup> ResourceNeedingCleanupPtr;
// ref-counted smart pointer
class SomeObjectThatMightKeepReferencesToResources
{
ResourceNeedingCleanupPtr pR;
void maybeSaveACopy(ResourceNeedingCleanupPtr& p)
{
if ( /* some condition is met */ )
pR = p;
}
};
// somewhere else in the code:
void MyFunction(SomeObjectThatMightKeepReferencesToResources& O)
{
ResourceNeedingCleanup R1( /*parameters*/) ;
shared_ptr<ResourceNeedingCleanup> pR2 =
new ResourceNeedingCleanup( /*parameters*/ );
try
{
R1.MethodThatMightThrowException();
pR2->MethodThatMightThrowException();
O->maybeSaveACopy(pR2);
}
catch ( /* something */ )
{
/* something */
}
// when we exit this block, R1 goes out of scope and executes its destructor
// which calls cleanup() whether or not an exception is thrown.
// pR2 goes out of scope. This is a shared reference-counted pointer.
// If O does not save a copy of pR2, then pR2 will be deleted automatically
// at this point. Otherwise, pR2 will be deleted automatically whenever
// O's destructor is called or O releases its ownership of pR2 and the
// reference count goes to zero.
}
Я думаю, что у меня есть корректная семантика; я не использовал shared_ptr очень сам, но я предпочитаю его auto_ptr <> - указатель на объект может только "принадлежать" одному auto_ptr <>. Я использовал CComPtr COM и вариант его, что я записал меня для "регулярного" (non-COM) объекты, который подобен shared_ptr <>, но имеет Присоединение () и Отсоединение () для передачи указателей от одного интеллектуального указателя до другого.
Непосредственно отвечать на Ваш вопрос, нет.
Это - умный способ реализовать ту функциональность, но это не надежно. Один путь, который приведет Вас к сбою, состоит в том, если Ваш "делают что-то" код, выдает исключение, которое не получено из Exception
. В этом случае Вы никогда не будете delete myObject
.
Здесь существует более важный текущий вопрос, и это - методологии, принятые программистами какого-то конкретного языка. Причина, которую Вы слышите о RAII, состоит в том, потому что программисты с намного большим опытом, чем Вы или я нашел, что в домене программирования на C++, что методология надежна. Можно полагаться на других программистов, использующих его, и другие программисты захотят полагаться на Вас использующий его.