MJBoa
MJBoa

Reputation: 175

How to use QNetworkAccessManager in different classes? General sharing of important data between classes?

I have a MainWindow application I'm working on to learn C++ and Qt (C++ and QT 4.8). I want to do HTTP requests in different objects of my application, such as Dialogs/Wizard and in the MainWindow. I know I'm basically supposed to have one QNetworkAccessManager per application. My question is, what is the proper way to pass this QNAM around between classes?

At the moment I have it as a pointer I pass to the constructor of my wizard but this seems... inelegant and inflexible. What is the proper way to give my Dialogs or whatever other classes I decide to make, access to my one QNetworkAccessManager? I guess I have the same question about any piece of data I need to give everything access to.

What is the properly C++-designed solution here? The singleton pattern seems like an option, but a bad one as I understand. I have a bit of code here to show my question.

My MainWindow constructor and slot which launch my wizard:

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

...

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

My Wizard Constructor in which I'm making network requests and parsing data after getting data from the user, and therefore in which I need a QNetworkAccessManager:

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

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

Upvotes: 6

Views: 2023

Answers (2)

Bobur
Bobur

Reputation: 575

Another way is shown in this post:

The canonical way to manage such global application-tied objects is to keep them as automatic variables in main and use helper functions to access them. The QPointer automatically tracks the lifetime of the object, and thus won't ever be dangling.

Thus:

main.h - interface

QNetworkAccessManager *nMgr();

main.cpp - implementation

// 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;
  ...
}

Upvotes: 0

Matthew
Matthew

Reputation: 2829

From your question, I think you're really asking which form of dependency injection (i.e. injecting your dependent QNetworkAccessManager into objects) to use.

In your case you're using Constructor injection. This is a perfectly known and accepted form of injection. It strongly communicates your wizard class depends upon the QNetworkAccessManager which makes your code easy for people to understand. If you were to use a singleton to simply grab a static QNetworkAccessManager from inside the wizard class implementation, while it has the benefit of removing the constructor injection, it hides that your wizard class uses the QNetworkAccessManager.

Another well known form of injection is Setter Injection i.e. setDelegate( delegate )

Professionally speaking there is nothing wrong with your current approach as again it clearly communicates your wizard class depends upon the QNetworkAccessManager object.

Here is a bit of reading if you if you're interested in learning more about dependency injection.

Dependency Injection

Dependency Injection in C++

Upvotes: 6

Related Questions