я нуждаюсь надежный информация об этой теме:
class MyClass, public QWidget
{
public:
MyClass( QWidget * parent = NULL )
:QWidget( parent ),
mpAnotherWidget( new QWidget( this ) ){};
private:
QWidget * mpAnotherWidget;
};
Конечно, вызывать виртуальные функции в списке инициализации ИЛИ конструктора — плохая идея. Вопрос: может ли этот код
mpAnotherWidget( new QWidget( this ) )
привести к неопределенному поведению ?! И если так: почему?
Пожалуйста, укажите ваши источники, если можете! Спасибо!
Это зависит от того, что QWidget
делает с указателем это дано. Совершенно нормально передавать ссылку или указатель на полуконструированный объект, если вызываемый код не имеет доступа к базовому объекту. Вам нужно заглянуть в документацию QWidget
знать, касается ли он объекта или просто сохраняет указатель.
В частном случае Qt, читая документацию, вызывает конструктор QWidget
аргумент имеет тип QWidget*
, а также this
используется только для приведения к базовому указателю. Получение указателя на базу гарантировано в 12.7 / 3, поскольку требование для преобразования состоит в том, что должно быть начато построение X и построение всех его прямых или косвенных оснований, которые прямо или косвенно вытекают из B. Затем указатель передается QWidget
конструктор, который может использовать его так, как он хочет, так как конструктор для базы QWidget
уже завершено до конструктора для mpAnotherWidget
начинается.
В общем, это необычная техника, и она рискованна, потому что неясно, какие ожидания может ожидать другой код.
Но, как вы правильно заметили, это код Qt. Здесь передача указателей на конструкторы довольно распространена и ожидаема. Ваши окна состоят из множества объектов, которые знают друг о друге.
В частности, QWidgets может иметь другие QWidgets в качестве родителей, и это поддерживается передачей родительского указателя дочернему элементу. И поскольку родительский класс часто является классом, создающим дочерние элементы, тогда указатель на родительский элемент просто this
, Так что ваш код совершенно нормальный стиль Qt.
Теперь это безопасно? Как написано, да. Конструктор для дочернего виджета, QWidget::QWidget
предполагает, что родительский указатель действительно указывает на уже построенный QWidget
и это в вашем примере. Но это не предполагает намного больше. Как это могло? QWidget ничего не знает о вашем классе. В частности, он не может даже вызывать чисто виртуальные методы, так как QWidget
не имеет тех.
Это нормально, если указатель не будет использоваться немедленно, но будет сохранен для будущего использования.
Но в случае QObject
производный, указатель передается для установления владения родительско-дочерним объектом, то есть указатель будет использоваться до того, как объект, на который он указывает, будет полностью создан. Таким образом, это неопределенное поведение — все может случиться, и если это произойдет, это будет плохо.