MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
В этом разделе кода после :
что делает
QMainWindow(parent),
ui(new Ui::MainWindow)
означает?
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
В этом разделе кода после :
что делает
QMainWindow(parent),
ui(new Ui::MainWindow)
означает?
Это вопрос С++. То, что вы смотрите, называется списками инициализации. QMainWindow(parent)
вызывает конструктор для MainWindow
суперкласса (QMainWindow
) и ui(new Ui::MainWindow)
строит член ui
.
В качестве дальнейшего объяснения обратите внимание, что класс, сгенерированный компилятором пользовательского интерфейса, также вызывается (в данном случае) MainWindow
, но он принадлежит пространству имен Ui
, поэтому его полное имя Ui::MainWindow
. Это явно не то же самое, что класс MainWindow
, который наследует от QMainWindow
. Однако класс QMainWindow
-derived имеет указатель-член (называемый Ui
) на Ui::MainWindow
, который инициализируется в конструкторе, как объяснялось выше. Посмотрите файл сгенерированный uic ui_mainwindow.h
, чтобы увидеть, как все части совпадают. Также обратите внимание, что члены Ui::MainWindow
являются общедоступными и поэтому полностью доступны в пределах MainWindow
.
Альтернативный дизайн заключается в объединении идентичности двух классов MainWindow
с использованием множественного наследования, получения собственного MainWindow
из QMainWindow
и Ui::MainWindow
. Однако код, созданный текущей версией QtCreator, следует шаблону состава, а не шаблону наследования.
Эти две строки представляют собой так называемый список инициализации и выполняются во время создания каждого экземпляра этого класса. Каждый класс, наследующий другого, должен содержать вызов конструктора суперкласса в этом списке.
Вы также можете написать:
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent)
{
ui = new Ui::MainWindow();
ui->setupUi(this);
}
который можно было бы найти более читаемым. Но использование списка инициализации немного быстрее и оптимизируется компилятором. Обратите внимание, что эти списки могут использоваться только в конструкторах, и вы не можете вызывать какие-либо функции объекта, потому что он еще не "живет". Но вы можете установить значение некоторых атрибутов и ссылаться на них в следующих операциях (например, чтобы избежать избыточности кода), например, в следующем примере:
#define DEFAULT_VALUE 1.0
class MyClass {
public:
MyClass() :
value1(DEFAULT_VALUE),
value2(value1)
{
}
MyClass(qreal value) :
value1(value),
value2(value1)
{
}
private:
qreal value1;
qreal value2;
};
Обратите внимание, что большинство компиляторов выдают вам предупреждение, если порядок членов в вашем списке инициализации не соответствует порядку в определении класса.