6

我正在开发一个 MainWindow 应用程序来学习 C++ 和 Qt(C++ 和 QT 4.8)。我想在我的应用程序的不同对象中执行 HTTP 请求,例如对话框/向导和 MainWindow。我知道我基本上应该每个应用程序有一个 QNetworkAccessManager。我的问题是,在课堂之间传递这个 QNAM 的正确方法是什么?

目前我把它作为一个指针传递给我的向导的构造函数,但这似乎......不优雅和不灵活。让我的对话框或我决定制作的任何其他类访问我的 QNetworkAccessManager 的正确方法是什么?我想我对我需要让所有东西访问的任何数据都有同样的问题。

这里正确的 C++ 设计的解决方案是什么?单例模式似乎是一种选择,但据我所知是一种糟糕的选择。我这里有一些代码来显示我的问题。

我的 MainWindow 构造函数和启动我的向导的插槽:

MyMainWindow::MyMainWindow
{
    qnam = new QNetworkAccessManager();
}

...

MyMainWindow::wizardStarter
{
    mywizard = MyWizard(vari, qnam, this);
}

我的向导构造函数,我在其中发出网络请求并在从用户获取数据后解析数据,因此我需要一个 QNetworkAccessManager:

MyWizard::MyWizard(SomeOtherArgument *vari, QNetworkAccessManager *qnam, QObject *parent)
{
    ...
    this->ourQnam = qnam;
    ...
}

MyWizard::launchRequest(QUrl newUrl)
{
    ourQnam->get(QNetworkRequest(newUrl));
}
4

2 回答 2

5

从你的问题来看,我认为你真的在问要使用哪种形式的依赖注入(即将你的依赖 QNetworkAccessManager 注入对象)。

在您的情况下,您使用的是Constructor injection。这是一种众所周知和公认的注射形式。它强烈地传达您的向导类依赖于QNetworkAccessManager,这使您的代码易于人们理解。如果您要使用单例从向导类实现中简单地获取静态 QNetworkAccessManager,虽然它具有删除构造函数注入的好处,但它隐藏了您的向导类使用 QNetworkAccessManager。

另一种众所周知的注入形式是Setter Injection ,即setDelegate( delegate )

从专业上讲,您当前的方法没有任何问题,因为它再次清楚地传达了您的向导类取决于QNetworkAccessManager 对象。

如果您有兴趣了解有关依赖注入的更多信息,请阅读以下内容。

依赖注入

C++ 中的依赖注入

于 2012-07-03T15:33:41.950 回答
0

这篇文章中显示了另一种方式:

管理此类全局应用程序绑定对象的规范方法是将它们作为自动变量保存main并使用辅助函数来访问它们。自动跟踪对象的QPointer生命周期,因此永远不会悬空。

因此:

main.h - 接口

QNetworkAccessManager *nMgr();

main.cpp - 实现

// This pointer is local to the translation unit, and is an
// implementation detail. It's not used anywhere else.
static QPointer<QNetworkAccessManager> globalManager;

// The global accessor method
QNetworkAccessManager *nMgr() {
  Q_ASSERT(!qApp || QThread::currentThread() == qApp->thread());
  return globalManager;
}

int main(int argc, char *argv[]) {
  QApplication app(argc, argv);
  QNetworkAccessManager mgr;
  globalManager = &mgr;
  ...
}
于 2018-06-08T08:36:18.693 回答