• QT基础教学(QT对象间的关系)



    前言

    本篇文章我们来讲解QT对象间的关系,理清楚QT对象间的关系是非常重要的,没有理清楚QT间的对象关系可能会导致内存的泄漏等各种问题的出现。

    资料合集地微信公众号:优质程序猿
    
    • 1

    一、QT间的父子关系

    在Qt中,父子关系是一种重要的概念,用于管理对象之间的层次结构和对象的生命周期。父子关系是通过设置对象的父对象来建立的。

    在Qt中,每个QObject及其派生类都可以具有一个父对象。当一个对象被设置为另一个对象的父对象时,父对象负责管理其子对象的内存释放和生命周期。

    以下是Qt中父子关系的几个重要方面:

    1.层次结构:
    通过将一个对象设置为另一个对象的父对象,您可以创建一个层次结构的对象组织结构。一个父对象可以有多个子对象,但一个子对象只能有一个父对象。

    示例:

    QWidget* parentWidget = new QWidget;
    QLabel* childLabel = new QLabel(parentWidget);
    
    
    • 1
    • 2
    • 3

    在上述示例中,创建了一个QWidget对象作为父对象,并创建了一个QLabel对象,将其设置为父对象的子对象。当父对象被销毁时,所有的子对象也会被自动销毁。

    2.内存管理:
    通过设置一个对象的父对象,父对象将负责管理其子对象的内存释放。当父对象被销毁时,会自动销毁其所有的子对象。

    示例:

    QWidget* parentWidget = new QWidget;
    QLabel* childLabel = new QLabel(parentWidget);
    delete parentWidget;  // 删除父对象
    
    
    • 1
    • 2
    • 3
    • 4

    在上述示例中,删除父对象parentWidget时,Qt会自动删除其子对象childLabel,无需手动释放内存。

    树形结构遍历:
    通过父子关系,可以创建一个对象的树形结构,通过父对象可以遍历整个树来访问和操作子对象。

    示例:

    QWidget* parentWidget = new QWidget;
    QLabel* childLabel = new QLabel(parentWidget);
    
    // 遍历子对象
    foreach (QObject* child, parentWidget->children()) {
        QLabel* label = qobject_cast<QLabel*>(child);
        if (label) {
            // 对子对象进行操作
            label->setText("Hello!");
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    在上述示例中,通过parentWidget->children()获取父对象的所有子对象,并使用qobject_cast进行类型转换。这使得可以方便地遍历整个对象树,访问和操作子对象。

    父子关系在Qt的对象模型中起到了重要的作用,它简化了对象的管理和内存释放工作,并提供了方便的对象组织结构和访问方式。了解和使用父子关系对于Qt的开发非常重要。

    对象间的父子关系:
    在这里插入图片描述
    销毁父对象后子对象也会被对应销毁:
    在这里插入图片描述

    二、聚合关系

    聚合关系(Aggregation Relationship):
    聚合关系表示一个对象包含了其他对象作为其一部分,但这些对象可以独立存在。聚合关系通常表现为一个对象作为另一个对象的成员变量。聚合关系中的对象之间没有明确的所有权关系。当包含的对象被销毁时,它们的内存管理由各自的拥有者负责。

    #include 
    
    class Car {
    public:
        // ...
    private:
        QStringList passengers;
    };
    
    int main()
    {
        Car car;
        car.passengers << "Alice" << "Bob";
    
        // ...
        return 0;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    三、组合关系

    组合关系(Composition Relationship):
    组合关系是聚合关系的一种特殊形式,表示一个对象是另一个对象的一部分,两者的生命周期紧密相关。组合关系通常表现为一个对象作为另一个对象的成员变量,并在组合对象被销毁时,成员对象也会被销毁。在Qt中,通常通过使用智能指针(如QSharedPointer)来管理组合关系。

    #include 
    
    class Engine {  // 引擎类
    public:
        // ...
    };
    
    class Car {
    public:
        Car() : engine(new Engine()) {}  // Car拥有一个引擎对象
    
    private:
        QSharedPointer<Engine> engine;
    };
    
    int main()
    {
        Car car;
        // ...
    
        // 当car对象被销毁时,引擎对象也会被销毁
        return 0;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    四、关联关系

    关联关系(Association Relationship):
    关联关系表示一个对象与其他对象之间存在某种关联或连接,但彼此之间没有拥有关系。关联关系可以是双向的或单向的。通常通过指针或引用来建立关联关系。

    class Teacher;  // 前向声明
    
    class Student {
    public:
        Student(Teacher* teacher) : myTeacher(teacher) {}  // 关联到一个教师对象
    
    private:
        Teacher* myTeacher;
    };
    
    class Teacher {
    public:
        Teacher(const QList<Student*>& students) : myStudents(students) {}  // 与多个学生对象关联
    
    private:
        QList<Student*> myStudents;
    };
    
    int main()
    {
        Teacher teacher;
        Student student(&teacher);
        // ...
    
        return 0;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    五、依赖关系

    依赖关系(Dependency Relationship):
    依赖关系表示一个对象在某种程度上依赖于另一个对象,但两者之间并没有直接的拥有或包含关系。依赖关系通常用于表示一个对象需要使用另一个对象的功能或服务。

    class Logger {
    public:
        void log(const QString& message) {
            // 日志记录功能
        }
    };
    
    class UserManager {
    public:
        UserManager(Logger& logger) : log(logger) {}  // 依赖Logger对象进行日志记录
    
        void addUser(const QString& username, const QString& password) {
            // 用户添加逻辑
    
            log.log("User added: " + username);  // 使用Logger对象进行日志记录
        }
    
    private:
        Logger& log;
    };
    
    int main()
    {
        Logger logger;
        UserManager manager(logger);
        manager.addUser("Alice", "123456");
    
        return 0;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    总结

    本篇文章就讲解到这里,大家看完文章后可以对上面讲解的知识进行复习巩固。

  • 相关阅读:
    Qt mysql客户端,测试
    大模型帮我梳理的docker命令
    好心情平台:看精神科医生前必知的5件事!让你少花钱少受罪
    MD5加密后16位与32位的区别 [ 详细 ]
    用路由器远程维护三菱PLC操作指南
    css案例16——ul无序列表(无li时无样式,有li后出现样式)
    Java初学者容易犯的错误,Java程序员必须知道的学习路线
    osg实现自定义插件读取自定义格式的模型文件到场景
    算法整理(二)
    Linux文件、目录操作命令
  • 原文地址:https://blog.csdn.net/m0_49476241/article/details/132918781