Использует & quot; это & ​​quot; в списке инициализации конструктора, особенно опасном с Qt?

я нуждаюсь надежный информация об этой теме:

class MyClass, public QWidget
{
public:
MyClass( QWidget * parent = NULL )
:QWidget( parent ),
mpAnotherWidget( new QWidget( this ) ){};
private:
QWidget * mpAnotherWidget;
};

Конечно, вызывать виртуальные функции в списке инициализации ИЛИ конструктора — плохая идея. Вопрос: может ли этот код

mpAnotherWidget( new QWidget( this ) )

привести к неопределенному поведению ?! И если так: почему?

Пожалуйста, укажите ваши источники, если можете! Спасибо!

3

Решение

Это зависит от того, что QWidget делает с указателем это дано. Совершенно нормально передавать ссылку или указатель на полуконструированный объект, если вызываемый код не имеет доступа к базовому объекту. Вам нужно заглянуть в документацию QWidget знать, касается ли он объекта или просто сохраняет указатель.


В частном случае Qt, читая документацию, вызывает конструктор QWidgetаргумент имеет тип QWidget*, а также this используется только для приведения к базовому указателю. Получение указателя на базу гарантировано в 12.7 / 3, поскольку требование для преобразования состоит в том, что должно быть начато построение X и построение всех его прямых или косвенных оснований, которые прямо или косвенно вытекают из B. Затем указатель передается QWidget конструктор, который может использовать его так, как он хочет, так как конструктор для базы QWidget уже завершено до конструктора для mpAnotherWidget начинается.

2

Другие решения

В общем, это необычная техника, и она рискованна, потому что неясно, какие ожидания может ожидать другой код.

Но, как вы правильно заметили, это код Qt. Здесь передача указателей на конструкторы довольно распространена и ожидаема. Ваши окна состоят из множества объектов, которые знают друг о друге.

В частности, QWidgets может иметь другие QWidgets в качестве родителей, и это поддерживается передачей родительского указателя дочернему элементу. И поскольку родительский класс часто является классом, создающим дочерние элементы, тогда указатель на родительский элемент просто this, Так что ваш код совершенно нормальный стиль Qt.

Теперь это безопасно? Как написано, да. Конструктор для дочернего виджета, QWidget::QWidget предполагает, что родительский указатель действительно указывает на уже построенный QWidgetи это в вашем примере. Но это не предполагает намного больше. Как это могло? QWidget ничего не знает о вашем классе. В частности, он не может даже вызывать чисто виртуальные методы, так как QWidget не имеет тех.

1

Это нормально, если указатель не будет использоваться немедленно, но будет сохранен для будущего использования.

Но в случае QObject производный, указатель передается для установления владения родительско-дочерним объектом, то есть указатель будет использоваться до того, как объект, на который он указывает, будет полностью создан. Таким образом, это неопределенное поведение — все может случиться, и если это произойдет, это будет плохо.

0
По вопросам рекламы [email protected]