Qt 成员初始化列表 代码解读

//在 mainwindow.h 中
class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);

private:
    Ui::MainWindow *ui;
    int a;
}


// 解读这段构造函数
MainWindow::MainWindow(QWidget *parent)
  : QMainWindow(parent)
  , ui(new Ui::MainWindow) // ui = =new Ui::MainWindow ;
  , a(99) // a = 99;
{
   ....
  // 首先  a(99) // a = 99; 就是等效于 a = 99 , ui(new Ui::MainWindow) 同理ui = =new Ui::MainWindow ;
  // QMainWindow(parent) 这句话什么意思
}

// 举个例子,两个class, 一个 Animal ,一个Dog,Dog继承Animal。
class Animal 
{
public:
    Animal(QString owner = "无主人") {
        this->m_owner = owner;
        qDebug() << "【Animal 初始化】动物的主人:" << m_owner;
    }
protected:
    QString m_owner;
};

class Dog : public Animal 
{
public:
    Dog(QString owner = "无主人");

    // 子类专属方法
    void bark();

private:
    QString m_breed; // 狗的品种
};

// Dog的构造函数
Dog::Dog(QString owner)
    : Animal(owner) // 重点!!!!
    , m_breed("金毛") //m_breed = "金毛"
{
    qDebug() << "【Dog 初始化】狗的专属能力已就绪(摇尾巴/叫)";
    qDebug() << "狗的品种:" << m_breed;
}

// bark 实现
void Dog::bark() {
    qDebug() << "【" << m_breed << "】对着 " << m_owner<< " 叫:汪汪汪!"; 吗?
}

int main()
{
  // 两种
  Dog dog1("小明"); // 指定主人
  dog1.bark();

  Dog dog2; // 默认,无主人,Dog(QString owner = "无主人");
  dog2.bark();
  return 0;
}

//灵活一点
class Dog : public Animal {
public:
    // 声明:支持自定义品种+主人,都给默认值(符合 Qt 构造函数风格)
    explicit Dog(QString breed = "金毛", QString owner = "无主人");
    void bark();
private:
    QString m_breed;
};

// 定义:参数和声明完全一致,不重复写默认参数
Dog::Dog(QString breed, QString owner)
    : Animal(owner)  // 先初始化父类(主人)
    , m_breed(breed) // 再初始化子类专属属性(品种)
{
    qDebug() << "【Dog 初始化】狗的品种:" << m_breed;
}

int main() 
{
    Dog dog1; // 默认:金毛 + 无主人
    dog1.bark(); // 【金毛】对着 无主人 叫:汪汪汪!

    Dog dog2("哈士奇"); // 自定义品种:哈士奇 + 默认主人
    dog2.bark(); // 【哈士奇】对着 无主人 叫:汪汪汪!

    Dog dog3("柴犬", "小红"); // 自定义品种+主人
    dog3.bark(); // 【柴犬】对着 小红 叫:汪汪汪!
    return 0;
}


C++ 规则:创建子类对象,先把父类那一部分构造好,再构造子类自己新增的部分。

#include <iostream>
using namespace std;

class Base{
public:
    Base(int a){
        cout << "父类Base构造,a=" << a << endl;
    }
};

class Son : public Base{
public:
    // 给参数默认值 99
    Son(int x = 99) : Base(x)
    {
        cout << "子类Son构造 x=" << x << endl;
    }
};

int main()
{
    Son s;      // ✅不传参,x使用默认值99 → Base(99)
    // Son s();  // ❌ 声明一个返回Son、无参数的函数s,不创建对象!不会调用构造!

    Son s2(10); // ✅传参 x=10 → Base(10)
    return 0;
}

输出:
父类Base构造,a=99
子类Son构造 x=99
父类Base构造,a=10
子类Son构造 x=10

### 如果父类是带参构造,不写初始化列表会直接编译报错!
class Base{
public:
    Base(int a){} //只有带参构造,没有无参Base()
};

class Son : public Base{
public:
    Son(int x)
    {
        // 编译器尝试自动 Base(); 但是Base没有无参构造!直接编译报错!
    }
};

编译器会试图自动调用父类无参构造;父类没有,就报错。
所以必须手动写 `Son(int x):Base(x){}`。

posted @ 2026-03-30 02:07  一见无始道成空  阅读(17)  评论(0)    收藏  举报