Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Trying to create a singleton and getting LNK2019 error
Forum Updated to NodeBB v4.3 + New Features

Trying to create a singleton and getting LNK2019 error

Scheduled Pinned Locked Moved Solved General and Desktop
singletonc++
18 Posts 4 Posters 8.3k Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • dheerendraD dheerendra

    It is C++ static variable issue. You did not initialise the static variable.
    Just add the following in MainWIndow.cpp

    MainWindow* MainWindow::w_instance = NULL;

    eggbertxE Offline
    eggbertxE Offline
    eggbertx
    wrote on last edited by
    #3

    @dheerendra
    I apologize if I sound dense, I'm not new to programming, but I'm relatively new to C++. Assuming you mean add it to the end of the main.cpp file, then MainWindow::instance() just returns NULL.

    kshegunovK 1 Reply Last reply
    0
    • eggbertxE eggbertx

      @dheerendra
      I apologize if I sound dense, I'm not new to programming, but I'm relatively new to C++. Assuming you mean add it to the end of the main.cpp file, then MainWindow::instance() just returns NULL.

      kshegunovK Offline
      kshegunovK Offline
      kshegunov
      Moderators
      wrote on last edited by
      #4

      Because you actually need an object the pointer is going to reference.

      MainWindow * MainWindow::instance()
      {
          if (!w_instance)
              w_instance = new MainWindow;
          return w_instance;
      }
      

      Here, however, I must strongly advise you not to use singletons in C++ (especially if you're not intimate with the language). They have many drawbacks, and in C++ the associated complications pile up really fast.

      Read and abide by the Qt Code of Conduct

      1 Reply Last reply
      2
      • eggbertxE eggbertx

        I'm trying to create a singleton function so I can access my MainWindow class as an instance from other classes, but in Windows I'm getting the following error:

        mainwindow.obj:-1: error: LNK2019: unresolved external symbol "private: static class MainWindow * MainWindow::w_instance" (?w_instance@MainWindow@@0PEAV1@EA) referenced in function "public: __cdecl MainWindow::MainWindow(class QWidget *)" (??0MainWindow@@QEAA@PEAVQWidget@@@Z)

        Here is the relevant code in my mainwindow.h:

        class MainWindow : public QMainWindow {
        	Q_OBJECT
        	public:
        		static MainWindow* instance();
        
        	private:
        		static MainWindow* w_instance;
        

        mainwindow.cpp

        MainWindow* MainWindow::instance() {
        	return w_instance;
        }
        

        What am I doing wrong?

        matthew.kuiashM Offline
        matthew.kuiashM Offline
        matthew.kuiash
        wrote on last edited by
        #5

        @eggbertx From which other object are you trying to access the window?

        If it's a QWidget child of the window (or child of child of child etc) then just use QWidget::window() to get access to the window object. You can also use qobject_cast on the returned value to cast safely to get to QMainWindow.

        Alternatively. Derive from QApplication and add a window accessor (setter/getter) there.

        The legendary cellist Pablo Casals was asked why he continued to practice at age 90. "Because I think I'm making progress," he replied.

        1 Reply Last reply
        0
        • eggbertxE Offline
          eggbertxE Offline
          eggbertx
          wrote on last edited by
          #6

          @kshegunov @matthew-kuiash
          I'm only trying to do this so I can access my main window's console (I'm making a Javascript IDE) from my util.cpp, nothing more, and the main window class has a console function for doing that. Ideally, I should be able to do

          MainWindow::instance().console("whatever");
          

          If a singleton is overkill, what would be a better way to do this?

          matthew.kuiashM 1 Reply Last reply
          0
          • eggbertxE eggbertx

            @kshegunov @matthew-kuiash
            I'm only trying to do this so I can access my main window's console (I'm making a Javascript IDE) from my util.cpp, nothing more, and the main window class has a console function for doing that. Ideally, I should be able to do

            MainWindow::instance().console("whatever");
            

            If a singleton is overkill, what would be a better way to do this?

            matthew.kuiashM Offline
            matthew.kuiashM Offline
            matthew.kuiash
            wrote on last edited by
            #7

            @eggbertx One possibility is for your JS engine to emit signals when it wants to output some text e.g. emit output("whatever") then connect that signal to your main window by implementing a "console" as a slot.

            Another would be to derive your own application and implement "console" there which could call through (proxy) to you main window.

            If it were me I'd go for the first option using a queued connection as this would mean that my JS engine would not get held up by UI activity e.g. the adding of text to the console. YMMV

            The legendary cellist Pablo Casals was asked why he continued to practice at age 90. "Because I think I'm making progress," he replied.

            1 Reply Last reply
            1
            • eggbertxE Offline
              eggbertxE Offline
              eggbertx
              wrote on last edited by
              #8

              @matthew-kuiash This IDE is for a specific game engine, and while the developer does plan on standardizing its console output (especially its debugging module) as far as I know, he isn't going to focus on that yet. For the time being, I'm just going to use it to output information about the IDE for simple debugging.

              1 Reply Last reply
              0
              • dheerendraD Offline
                dheerendraD Offline
                dheerendra
                Qt Champions 2022
                wrote on last edited by
                #9

                add this line to the beginning of you MainWindow.cpp file. Just see the code snippet.

                #include "MainWindow.h"

                MainWindow* MainWindow::w_instance = NULL;

                MainWindow::MainWindow(QWidget *parent)
                : QMainWindow(parent)
                {
                }

                Dheerendra
                @Community Service
                Certified Qt Specialist
                http://www.pthinks.com

                eggbertxE 1 Reply Last reply
                5
                • dheerendraD dheerendra

                  add this line to the beginning of you MainWindow.cpp file. Just see the code snippet.

                  #include "MainWindow.h"

                  MainWindow* MainWindow::w_instance = NULL;

                  MainWindow::MainWindow(QWidget *parent)
                  : QMainWindow(parent)
                  {
                  }

                  eggbertxE Offline
                  eggbertxE Offline
                  eggbertx
                  wrote on last edited by
                  #10

                  @dheerendra
                  Alright, that seems to be working but now I've run into a another problem. I can send the MainWindow::console string argument to the Qt Creator console via

                  qDebug() << str;
                  

                  but regardless of how many times I call the function, it's only appending said argument to the console widget (QTextEdit) via

                  ui->consoleWidget->appendPlainText(str.toString());
                  

                  the first time MainWindow::console("whatever") is called.

                  1 Reply Last reply
                  0
                  • dheerendraD Offline
                    dheerendraD Offline
                    dheerendra
                    Qt Champions 2022
                    wrote on last edited by dheerendra
                    #11

                    I did not understand issue clearly. Let me try to answer.

                    1. when you put the qDebug() << str , are you seeing out put on the qtcreator console window ?
                    2. Are you also appending the string to your textedit as well ?

                    Dheerendra
                    @Community Service
                    Certified Qt Specialist
                    http://www.pthinks.com

                    eggbertxE 1 Reply Last reply
                    8
                    • dheerendraD dheerendra

                      I did not understand issue clearly. Let me try to answer.

                      1. when you put the qDebug() << str , are you seeing out put on the qtcreator console window ?
                      2. Are you also appending the string to your textedit as well ?
                      eggbertxE Offline
                      eggbertxE Offline
                      eggbertx
                      wrote on last edited by
                      #12

                      @dheerendra

                      1. yes, every time it's called
                      2. yes, but it's only showing up the first time MainWindow::console("whatever") is called, regardless from where it's called.
                      1 Reply Last reply
                      0
                      • eggbertxE Offline
                        eggbertxE Offline
                        eggbertx
                        wrote on last edited by eggbertx
                        #13

                        Is bumping a thread for sake of trying to resolve the issue against the rules?

                        kshegunovK 1 Reply Last reply
                        0
                        • eggbertxE eggbertx

                          Is bumping a thread for sake of trying to resolve the issue against the rules?

                          kshegunovK Offline
                          kshegunovK Offline
                          kshegunov
                          Moderators
                          wrote on last edited by kshegunov
                          #14

                          @eggbertx said in Trying to create a singleton and getting LNK2019 error:

                          Is bumping a thread for sake of trying to resolve the issue against the rules?

                          No it's not, it's the preferred way.

                          As for the issue. I wouldn't approach the issue that way. Singletons are pretty bad, and one should do well to avoid them if possible. Whenever one can't avoid using a singleton I always prefer the "pseudo-singleton" approach Qt employs, something along those lines:
                          header

                          class Singleton : public QObject
                          {
                          public:
                              Singleton(QObject * parent = Q_NULLPTR);
                          
                              static Singleton * instance();
                              
                          private:
                              static Singleton * _instance;
                          };
                          

                          source

                          Singleton * Singleton::_instance = Q_NULLPTR;
                          
                          Singleton::Singleton(QObject * parent)
                              : QObject(parent)
                          {
                              Q_ASSERT(!_instance);
                              _instance = this;
                          }
                          
                          Singleton * Singleton::instance()
                          {
                              return _instance;
                          }
                          

                          Then you create as a stack object in main() and use everywhere:

                          int main(int argc, char ** argv)
                          {
                              QApplication app(argc, argv);
                          
                              Singleton singleton(&app);
                              // Rest of code
                          }
                          

                          This particular implementation does not suffer the usual problems with lazy-initialization singletons as memory leaking and thread-unsafe creation, but still does couple up the components. Anyway, a so-constructed global object one can use to connect with signals and slots to whatever UI control is needed at any point and does not impose a strange and unnecessary way of creating the main window. For example consider this:

                          void Singleton::console(const QString & line) // Make a slot in the header
                          {
                              QTextStream stream(&allText); // allText is a member variable of type QString
                              stream << line << endl;
                          
                              emit textChanged(allText);  // void textChanged(const QString &) is a notification signal
                          }
                          

                          Then one could directly hook up this class' instance to the UI component:

                          class MainWindow : public QMainWindow
                          {
                          	Q_OBJECT
                          
                          public:
                              MainWindow()
                                  : QMainWindow(Q_NULLPTR)
                              {
                                  ui.setupUi(this); // Or w/e is needed to set up the UI
                          
                                  QObject::connect(Singleton::instance(), &Singleton::textChanged, ui.textEditWidget, &QTextEdit::setPlainText); // All that's really needed
                              }
                          };
                          

                          Read and abide by the Qt Code of Conduct

                          eggbertxE 1 Reply Last reply
                          0
                          • kshegunovK kshegunov

                            @eggbertx said in Trying to create a singleton and getting LNK2019 error:

                            Is bumping a thread for sake of trying to resolve the issue against the rules?

                            No it's not, it's the preferred way.

                            As for the issue. I wouldn't approach the issue that way. Singletons are pretty bad, and one should do well to avoid them if possible. Whenever one can't avoid using a singleton I always prefer the "pseudo-singleton" approach Qt employs, something along those lines:
                            header

                            class Singleton : public QObject
                            {
                            public:
                                Singleton(QObject * parent = Q_NULLPTR);
                            
                                static Singleton * instance();
                                
                            private:
                                static Singleton * _instance;
                            };
                            

                            source

                            Singleton * Singleton::_instance = Q_NULLPTR;
                            
                            Singleton::Singleton(QObject * parent)
                                : QObject(parent)
                            {
                                Q_ASSERT(!_instance);
                                _instance = this;
                            }
                            
                            Singleton * Singleton::instance()
                            {
                                return _instance;
                            }
                            

                            Then you create as a stack object in main() and use everywhere:

                            int main(int argc, char ** argv)
                            {
                                QApplication app(argc, argv);
                            
                                Singleton singleton(&app);
                                // Rest of code
                            }
                            

                            This particular implementation does not suffer the usual problems with lazy-initialization singletons as memory leaking and thread-unsafe creation, but still does couple up the components. Anyway, a so-constructed global object one can use to connect with signals and slots to whatever UI control is needed at any point and does not impose a strange and unnecessary way of creating the main window. For example consider this:

                            void Singleton::console(const QString & line) // Make a slot in the header
                            {
                                QTextStream stream(&allText); // allText is a member variable of type QString
                                stream << line << endl;
                            
                                emit textChanged(allText);  // void textChanged(const QString &) is a notification signal
                            }
                            

                            Then one could directly hook up this class' instance to the UI component:

                            class MainWindow : public QMainWindow
                            {
                            	Q_OBJECT
                            
                            public:
                                MainWindow()
                                    : QMainWindow(Q_NULLPTR)
                                {
                                    ui.setupUi(this); // Or w/e is needed to set up the UI
                            
                                    QObject::connect(Singleton::instance(), &Singleton::textChanged, ui.textEditWidget, &QTextEdit::setPlainText); // All that's really needed
                                }
                            };
                            
                            eggbertxE Offline
                            eggbertxE Offline
                            eggbertx
                            wrote on last edited by
                            #15

                            @kshegunov The first example works perfectly. And thus far, I've only been using signals and slots for actions and button presses.

                            kshegunovK 1 Reply Last reply
                            0
                            • eggbertxE eggbertx

                              @kshegunov The first example works perfectly. And thus far, I've only been using signals and slots for actions and button presses.

                              kshegunovK Offline
                              kshegunovK Offline
                              kshegunov
                              Moderators
                              wrote on last edited by
                              #16

                              I don't follow. What first example you mean?

                              Read and abide by the Qt Code of Conduct

                              eggbertxE 1 Reply Last reply
                              0
                              • kshegunovK kshegunov

                                I don't follow. What first example you mean?

                                eggbertxE Offline
                                eggbertxE Offline
                                eggbertx
                                wrote on last edited by
                                #17

                                @kshegunov Sorry, I meant the second code block, not the first. I'm not very familiar with assertions in general, so I've never heard of Q_ASSERT. Adding the code in the second block fixed the issue.

                                kshegunovK 1 Reply Last reply
                                0
                                • eggbertxE eggbertx

                                  @kshegunov Sorry, I meant the second code block, not the first. I'm not very familiar with assertions in general, so I've never heard of Q_ASSERT. Adding the code in the second block fixed the issue.

                                  kshegunovK Offline
                                  kshegunovK Offline
                                  kshegunov
                                  Moderators
                                  wrote on last edited by
                                  #18

                                  @eggbertx said in Trying to create a singleton and getting LNK2019 error:

                                  Sorry, I meant the second code block, not the first. I'm not very familiar with assertions in general, so I've never heard of Q_ASSERT.

                                  The assertion here is only a tool to detect creating more than one instance of the class. Q_ASSERT is a Qt macro for regular debug assertions, it will be removed in release mode, so its purpose (as assertions in general) is to catch programmer errors while debugging. So if you use the class above like this:

                                  Singleton object1;
                                  Singleton object2; //< Here the assertion will be tripped and you can catch the error while debugging
                                  

                                  Adding the code in the second block fixed the issue.

                                  Do you mean the main window constructor where the connect is made? All code blocks are part of one single example, so I'd expect them to work together only. :)

                                  Read and abide by the Qt Code of Conduct

                                  1 Reply Last reply
                                  1

                                  • Login

                                  • Login or register to search.
                                  • First post
                                    Last post
                                  0
                                  • Categories
                                  • Recent
                                  • Tags
                                  • Popular
                                  • Users
                                  • Groups
                                  • Search
                                  • Get Qt Extensions
                                  • Unsolved