【Visual Studio】Qt 在其他 cpp 文件中调用主工程下文件中的函数

知识不是单独的,一定是成体系的。更多我的个人总结和相关经验可查阅这个专栏:Visual Studio

还整了一个如何在其他文件中调用 ui 控件的文章,感兴趣可以看:【Visual Studio】Qt 在其他 cpp 文件中调用操作 ui 界面控件

主界面工程为 A,添加的文件名字为 test,目标是在 test 文件里操作 A 工程里的函数。


简洁版直接看这个截图就行,大意就是将老的实例化 ui 变成指针,将地址传递给 p_ui,然后通过调用 p_ui 来间接调用 ui

名称解释:

  • c_test 表示新建的类
  • p_ui 表示新建的类里的指针类型的成员变量
  • testFun() 表示新建的类的函数
  • mc_test 实例化的类,用来调用新建的 c_test 的类

详细版可以看下边这些。

创建一个原始工程名字为 A

为了更好地演示,首先创建一个原始工程,名字为 A,定义一个函数 inAFun(),函数功能是打印一段文字。效果如下图所示:

在这里插入图片描述


工程的四个项目文件分别如下:

A.ui

在这里插入图片描述


A.h

// A.h
#pragma once

#include <QtWidgets/QMainWindow>
#include "ui_A.h"

class A : public QMainWindow
{
    
    
    Q_OBJECT

public:
    A(QWidget* parent = nullptr);
    ~A();

private slots:
    void inAFun();

private:
    Ui::AClass ui;
};

A.cpp

// A.cpp
#include "A.h"

A::A(QWidget* parent) : QMainWindow(parent)
{
    
    
    ui.setupUi(this);

    inAFun();
}

A::~A()
{
    
    }

void A::inAFun()
{
    
    
    ui.textBrowser->insertPlainText("This is a text from A.cpp!\n");
}

main.cpp

// main.cpp
// main.cpp
#include "A.h"
#include <QtWidgets/QApplication>

int main(int argc, char* argv[])
{
    
    
    QApplication a(argc, argv);
    A w;
    w.show();
    return a.exec();
}

修改后

接下来将创建一个 test.h 和一个 test.cpp 文件,并实现在 test.cpp 中调用 A.cpp 中的函数 inAFun(),也会打印出来一段文字标记来自 inAFun()。最终效果如下图所示:

在这里插入图片描述


A.h

// A.h
#pragma once

#include <QtWidgets/QMainWindow>
#include "ui_A.h"

class A : public QMainWindow
{
    
    
    Q_OBJECT

public:
    A(QWidget* parent = nullptr);
    ~A();

public slots:   // 变更为 public 或者 public slots
    void inAFun();

private:
    Ui::AClass ui;
};


确保 inAFun() 函数在 A 类中是 public 或者是 public slots,只有这样才能在其他类中使用。


A.cpp

// A.cpp
#include "A.h"

A::A(QWidget* parent) : QMainWindow(parent)
{
    
    
    ui.setupUi(this);

    inAFun();
}

A::~A()
{
    
    }

void A::inAFun()
{
    
    
    ui.textBrowser->insertPlainText("This is a text from A.cpp!\n");
}

不用改动。

这里的详细解释可以参考:【Visual Studio】Qt 在其他 cpp 文件中调用操作 ui 界面控件


test.h

// test.h
#pragma once

#include "A.h"

class c_test
{
    
    
public:
    c_test(A* a_ptr);  // 在构造函数中接收一个 A 类的指针
    ~c_test();

    void callAFunction();

private:
    A* a_object;  // 储存一个 A 类的指针
};

test.h 中包含 A.h


test.cpp

#include "test.h"

c_test::c_test(A* a_ptr) : a_object(a_ptr)  // 初始化 A 类的指针
{
    
    }

c_test::~c_test()
{
    
    }

void c_test::callAFunction()
{
    
    
    a_object->inAFun();  // 通过 A 类的指针来调用 inAFun() 方法
}


重点看一下 c_test::c_test(A* a_ptr) : a_object(a_ptr):是使用初始化列表语法来初始化 c_test 类的 a_object 成员。这行代码的意思是,当 c_test 类的对象被构造时,它的 a_object 成员应该被初始化为传递给 c_test 类构造函数的参数 a_ptr。这样,就能够在 c_test 类的其他方法中,通过 a_object 指针访问 A 类的对象了。

C++ 的初始化列表语法。初始化列表出现在构造函数后面,由冒号开始,并包含一个或多个用逗号分隔的成员初始化器。每个成员初始化器由一个数据成员(或基类)的名称和一对括号组成,括号内包含了用来初始化该数据成员的值或表达式。

这种初始化方式主要有两个优点:

更高效:对于某些类型的数据成员(如 const 或引用类型),你必须在构造函数体外进行初始化,因为这些类型的成员变量不能在构造函数体内被赋值。即使对于那些可以在构造函数体内赋值的数据成员,使用初始化列表通常也会更高效,因为它可以避免先调用默认构造函数再调用赋值操作符的额外开销。

更安全:如果一个类的数据成员是另一个类对象,而后者的构造函数需要一些参数,那么你就需要在初始化列表中传递这些参数,否则你无法在构造函数体内进行初始化,因为此时对象已经被默认构造函数构造好了。


main.cpp

// main.cpp
#include "A.h"
#include "test.h"  // 包含 test.h 文件
#include <QtWidgets/QApplication>

int main(int argc, char* argv[])
{
    
    
    QApplication a(argc, argv);
    
    A w;
    w.show();

    c_test mc_test(&w);  // 传递 A 类对象的地址给 c_test 类的构造函数
    mc_test.callAFunction();  // 调用 Test 类的 callAFunction() 方法,这会触发 A 类的 inAFun() 方法

    return a.exec();
}

现在,当运行程序时,main.cpp 文件会创建一个 A 类的对象并展示它的窗口。

然后创建一个 c_test 类的对象,并将 A 类的对象的地址作为参数传递给 c_test 类的构造函数。这时 callAFunction() 方法就能够调用 A 类的 inAFun() 方法,而且你应该能够在 A 类的 QTextBrowser 中看到 inAFun() 插入的文本。


Ref.

  1. Qt中,在另一cpp文件操作ui界面的相关控件
  2. [Qt] [UI] 多个类中操作同一个UI界面

Backup

// main.cpp
#include "GUI_NatNet_VTK.h"
#include <QtWidgets/QApplication>

GUI_NatNet_VTK* w;

int main(int argc, char *argv[])
{
    
    
    QApplication a(argc, argv);
    w = new GUI_NatNet_VTK();

    w->show();
    return a.exec();
}
// GUI_NatNet_VTK.h
private slots:
    void on_pushButtonStart_clicked();
    void on_pushButtonPause_clicked();
    void on_pushButtonStop_clicked();

    void discoverNatNet();
    void connectNatNet();

    friend void displayMotion(GUI_NatNet_VTK &p_ui, double **dynamicArray);
\\ GUI_NatNet_VTK.cpp
void displayMotion(GUI_NatNet_VTK& p_ui, double **dynamicArray)
{
    
    
    p_ui.ui.labelRBX->setText(QString::number(dynamicArray[0][0]));
    p_ui.ui.labelRBY->setText(QString::number(dynamicArray[0][1]));
    p_ui.ui.labelRBZ->setText(QString::number(dynamicArray[0][2]));
}

Ref.

  1. C++ 友元函数

猜你喜欢

转载自blog.csdn.net/weixin_36815313/article/details/131820932