[Solved] Trouble with implementing Singleton



  • Hi!

    I am trying to get access to the main window within Qt from a callback function, so I thougth first step would be to implement a Singleton to have a pointer to the instance from outside of the object. I read "some easy docu":http://www.qtcentre.org/wiki/index.php?title=Singleton_pattern for the Singleton and have more or less repeated like this:

    mainwindow.h:
    @
    public:
    explicit MainWindow(QWidget parent = 0);
    ~MainWindow();
    static MainWindow
    inst; // My Singleton pointer as far as I understand my code...
    @

    mainwindow.cpp:
    @
    MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) {
    if ( !inst ) this->inst = this;
    if ( !this->inst ) MainWindow::inst = this;
    ui->setupUi(this);
    ...
    }
    @

    Now, in the first two lines of the MainWindow constructor, I get 4(!) times the error "Fehler: undefined reference to `MainWindow::inst'". So the compiler has understood all 4 references to "inst" in the same way and made 4 times "MainWindow::inst" from it, which looks perfect from my point of view. However, even interpreted correctly, it complains that it doesn't find the reference, which I don't really understand because haven't I defined it correctly in the header file? It doesn't look difficult, but I can't see the problem, so does anyone else see it?

    Thanks for your help,
    Stephan



  • Hi, you can also ask Qt's QApplication object for its current main window: QApplication::activeWindow();

    It's a static method so it should be ok to use from your callback function.


  • Moderators

    Singletons should not expose their constructors, destructors and the instance to the public. So in that, your code is wrong.

    Please consult this guide, it has a nice description of the whole topic: "link":http://www.yolinux.com/TUTORIALS/C++Singleton.html.



  • @hskoglund
    Ok, that indeed works for the callback function, thanks for the hint. As I am pretty new to Qt I must admit all these little "tools" of the libraries, etc. are not present yet.

    Nevertheless, do you have any idea, why the example given above would not work? It's just for my interest as I probably use your suggestion in the long run, but I would just like to know...

    Stephan



  • @sierdzio

    Thanks for the answer, I am aware of the shortcomings. Initially I had followed these concepts already, but while searching for the problem I tried to make the code more "open" to find the problem behind. Also the guide outlines pretty much exactly the same pattern that I have mentioned, so that's even more of a motivator to wonder what's wrong in the very short outline I have posted. So you see, where the syntactic error is located?

    Stephan


  • Moderators

    You are using "this" to point to a static variable (which is available without object). I suspect that might make the compiler unhappy.



  • Not unhappy, I'd say instead "confusing", prefixing a static variable with this-> works the same as prefixing it with MainWindow:: or, if inside MainWindow class, not prefixing it at all.

    The problem is that there's no instance of inst declared (it's just defined), that's why the linker returns the error. To get around it, for example declare it directly after the constructor, like this;
    @
    MainWindow* MainWindow::inst = 0;
    @



  • AFAIK is a static variable always available in the instance context, just only - of course - not the other way around?!? Anyway, that's just one of the four "trials" to access the variable, if only that would be the location of protest from the compiler I would happily change it, but it complains about all 3 others as well. So how would I access that variable???

    Stephan



  • Actually I think it's the linker that complains, because it can't find any location for your static inst variable (and why you need to declare an instance as in my example above).

    Re. accessing the variable, so either of the 3 ways are fine: prefixing with MainWindow::, prefixing with this-> or not prefixing it at all.
    (Of course only the first way is valid outside the MainWindow class :-)



  • If I change the definition according to my first post I only receive errors:

    @
    static MainWindow* MainWindow::inst;
    @
    -> Fehler: extra qualification 'MainWindow::' on member 'inst' [-fpermissive]
    static MainWindow* MainWindow::inst;

    @
    static MainWindow* inst = 0;
    @
    -> Fehler: 'constexpr' needed for in-class initialization of static data member 'MainWindow* MainWindow::inst' of non-integral type [-fpermissive]

    @
    static MainWindow* MainWindow::inst = 0;
    @
    -> Fehler: extra qualification 'MainWindow::' on member 'inst' [-fpermissive]
    -> Fehler: 'constexpr' needed for in-class initialization of static data member 'MainWindow* MainWindow::inst' of non-integral type [-fpermissive]

    @hskoglund you recommend to declare it without "static", is that intentionelly? If you vote for static as well, then isn't it exactly the way I posted it at the beginning?

    Stephan



  • Hi, to make it work you'll have to declare that variable inst 2 times, first inside your MainWindow class (in the .h file):
    @
    static MainWindow* inst; // My Singleton pointer as far as I understand my code...
    @

    Next, you'll have to write it one more time to create an instance of inst, easiest as I write above, insert it just after the constructor:
    @
    ...
    if ( !inst ) this->inst = this;
    if ( !this->inst ) MainWindow::inst = this;
    ui->setupUi(this);
    }

    MainWindow* MainWindow::inst = 0; // <--- good place

    MainWindow::~MainWindow()
    {
    delete ui;
    }
    @



  • Wow, that works, thanks a lot for the hint! I must admit I haven't understood in the first place, I forgot why I have to declare it twice even I thought I knew the difference between declaration and definition, but here I missed out. Have to re-read some stuff I guess.

    Thanks for your patience!
    Stephan


  • Lifetime Qt Champion

    Hi,

    Out of curiosity, are your callback called from another thread ?



  • Hoi,

    yes, indeed, that's why I implemented the Singleton. I receive events from a dll which facilitates an own thread. This one wants to call back on a standard C function which was subject to another thread I opened here and it's also already solved. But from that function obviously I want to feed that information back into the "object-oriented system" anyhow, so at one point I need a static pointer to an instance. That's exactly this point we have discussed here.

    I was actually missing the "double" definition described by hskoglung above, after I added that everything was fine.

    Stephan


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.