Новый вопрос в Qt

MainWindow::MainWindow(QWidget *parent) :  
    QMainWindow(parent),  
    ui(new Ui::MainWindow)  
{  
    ui->setupUi(this);  
}

В этом разделе кода после : что делает

QMainWindow(parent),
ui(new Ui::MainWindow)  

означает?

Ответ 1

Это вопрос С++. То, что вы смотрите, называется списками инициализации. QMainWindow(parent) вызывает конструктор для MainWindow суперкласса (QMainWindow) и ui(new Ui::MainWindow) строит член ui.

Ответ 2

В качестве дальнейшего объяснения обратите внимание, что класс, сгенерированный компилятором пользовательского интерфейса, также вызывается (в данном случае) MainWindow, но он принадлежит пространству имен Ui, поэтому его полное имя Ui::MainWindow. Это явно не то же самое, что класс MainWindow, который наследует от QMainWindow. Однако класс QMainWindow -derived имеет указатель-член (называемый Ui) на Ui::MainWindow, который инициализируется в конструкторе, как объяснялось выше. Посмотрите файл сгенерированный uic ui_mainwindow.h, чтобы увидеть, как все части совпадают. Также обратите внимание, что члены Ui::MainWindow являются общедоступными и поэтому полностью доступны в пределах MainWindow.

Альтернативный дизайн заключается в объединении идентичности двух классов MainWindow с использованием множественного наследования, получения собственного MainWindow из QMainWindow и Ui::MainWindow. Однако код, созданный текущей версией QtCreator, следует шаблону состава, а не шаблону наследования.

Ответ 3

Эти две строки представляют собой так называемый список инициализации и выполняются во время создания каждого экземпляра этого класса. Каждый класс, наследующий другого, должен содержать вызов конструктора суперкласса в этом списке.

Вы также можете написать:

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;
};

Обратите внимание, что большинство компиляторов выдают вам предупреждение, если порядок членов в вашем списке инициализации не соответствует порядку в определении класса.