如何从另一个函数中访问一个功能,从C 中的第三个访问

How to access stuff in one function from another, called from third in c++

本文关键字:访问 三个 一个 另一个 函数 功能      更新时间:2023-10-16

我有此代码:

void Forms::login() {
    LoginForm *loginForm = new LoginForm;
    loginForm->show();
}
void Forms::startGame() {
    WorldForm *worldForm = new WorldForm;
    worldForm->show();
    loginForm->hide();
}

因此,我试图将所有逻辑与一个单独的文件联系起来,例如logics.cpp。首先,我仅使用常规功能,但是我无法从StartGame访问登录名(因为我不能简单地将其添加到.h文件中,这会崩溃所有程序,不要问为什么 - QT QUTER。这些类型是qwidgets)。现在我需要的是:

  1. 如何添加WorldForm&登录到类表单的根(或标题文件)的根,我不能这样做。

  2. 最终目标是调用startGame()(在这种情况下,是另一个文件中的另一个类的forms :: startGame()为静态函数),而startGame()应该能够隐藏登录名,如上所示。

我甚至不能这样做:

void Forms::world(int a) {
    WorldForm *worldForm = new WorldForm;
    if(a==0) {
        worldForm->show();
    }else{
        worldForm->hide();
    }
}

因为我需要worldForm仅创建一次,这将为每个呼叫创建很多实例1。

这是我的代码:https://github.com/ewancoder/game

您正在寻找的是成员变量,而单身模式则以QApplication的样式完成。

您似乎正在做的是声明一个小部件类型的全局变量:

// interface (.h)
extern QWidget myWidget;
// implementation (.cpp)
QWidget myWidget;

这将从不工作,因为在main()启动之前发生了这样的对象的构建!这是您在Delphi和C 之间所拥有的关键差异。在Delphi中,您必须自己调用对象的构造函数。在C 中,它是自动完成的 - 对于全局变量,所有内容都是由main()执行时构建的。您需要使用指针。

可以声明和实现Forms类,如下所示。

类是不可复制的,因为QScopedPointer不可复制,因此我们应该向人类读者明确。无论如何,这堂课都没有充分的理由可以复制,即使我们使用了QSharedPointer

使用QScopedPointer智能指针,以使表格不会泄漏。QScopedPointer的破坏者会自动释放分配的形式(如果有)。它可以用作布尔,当它是非效果时是真的。

班级强制执行一个不变的,即它的实例。该实例应在QApplication之后的main()函数中构造。您可以使用静态Forms::instance()方法从任何地方访问此实例。

例如,在LoginForm::on_loadButton_clicked()中,您将使用

Forms::instance()->world();
// core.h - interface
#include <QScopedPointer>
class LoginForm;
class WorldForm;
class Forms {
    Q_DISABLE_COPY(Forms)
    QScopedPointer<LoginForm> m_loginForm;
    QScopedPointer<WorldForm> m_worldForm;
    static Forms * m_instance; // declaration
public:
    Forms();
    ~Forms();
    static Forms * instance();
    void login(int act = 0);
    void world();
};
// forms.cpp - implementation
#include "core.h"
#include "Forms/loginform.h"
#include "Forms/worldform.h"
Forms * Forms::m_instance = 0; // definition
// The runtime default-constructs static class members, so technically
// the explicit initialization to a null pointer is not necessary.
void Forms::login(int act) {
    if (!m_loginForm) m_loginForm.reset(new LoginForm);
    switch(act) {
    case 1:
        m_loginForm->hide();
        break;
    default:
        m_loginForm->show();
    }
}
void Forms::world() {
    if (!m_worldForm) m_worldForm.reset(new WorldForm);
    m_worldForm->show();
}
Forms::Forms() {
    Q_ASSERT(! m_instance);
    m_instance = this;
}
Forms::~Forms() {
    m_instance = 0;
}
Forms * Forms::instance() {
    return m_instance;
}
// main.cpp
#include <QApplication>
#include "Classes/core.h"
int main(int argc, char *argv[]) {
    QApplication game(argc, argv);
    Forms forms;
    forms.login();
    return game.exec();
    // The local object instances are destructed in C++-generated-code.
    // The order of destruction is opposite to the order of definition.
    // The compiler puts the following code "here":
    // forms.~Forms();
    // game.~QApplication();
}

所以,有人可能会问,为什么不使Forms类中的所有内容静态完成呢?由于静态类成员变量的寿命,这是不可能的。在 main()启动之前,构建此类成员,然后在 main()结束后破坏了。这是一个大问题,因为:

  1. 您无法利用智能指针到小部件,因为当QApplication不再存在时,它们将被删除,并且不允许。您可以手动reset()手动指示,但这确实打败了智能指针的目的。智能指针在那里,因此您不必手动管理内存。

  2. 由于Forms类没有实例 - 它只是静态成员的包装器 - 驱动器永远不会被调用,并且您无法利用C 自动清理成员。

您可以做的最多的是使所有方法成员变量 。因此,这仍然可以,但是使方法实现很麻烦:

class Forms {
    Q_DISABLE_COPY(Forms)
    QScopedPointer<LoginForm> m_loginForm;
    QScopedPointer<WorldForm> m_worldForm;
    static Forms * m_instance;
public:
    Forms();
    ~Forms();
    static Forms * instance();
    static void login(int act = 0);
    static void world();
};
void Forms::login(int act) {
    Forms * inst = instance();
    if (!inst->m_loginForm) inst->m_loginForm.reset(new LoginForm);
    ...
}

但这肯定是错误的:

// WRONG
class Forms {
    static QScopedPointer<LoginForm> m_loginForm;
    static QScopedPointer<WorldForm> m_worldForm;
public:
    static void login(int act = 0);
    static void world();
};

这是错误的,因为范围的指针被破坏,因此在main()结束后删除了表格。周围没有QApplication,您不允许使用小部件(甚至没有破坏它们)做任何事情。

要解决此问题,您需要在类似静态击路仪的方法中明确释放表单实例,您必须手动调用以删除表单。然后,您的主要内容将成为用C 语法编写的Delphi。您对Delphi成语有很大的偏见。这些成语不属于C - 您必须学习它们。C 编译器会在Delphi中进行大量代码生成。您应该利用这一点。

// AWKWARD: Delphi code in C++ syntax
int main(int argc, char *argv[]) {
    QApplication game(argc, argv);
    Forms::login();
    int rc = game.exec();
    Forms::destroy();
    return rc;
}
// BRAINDEAD: Delphi code in C++ syntax
class Forms {
    static QScopedPointer<LoginForm> m_loginForm;
    static QScopedPointer<WorldForm> m_worldForm;
public:
    static void login(int act = 0);
    static void world();
    static void destroy();
};

这希望可以解释为什么C 比Delphi更强大。在Delphi中,您必须担心C 编译器会照顾的很多事情,从而阻止您忘记重要的事情,例如释放记忆或发布其他资源。

相关文章: