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. 'MainWindow' does not name a type
QtWS25 Last Chance

'MainWindow' does not name a type

Scheduled Pinned Locked Moved Solved General and Desktop
7 Posts 3 Posters 4.1k Views
  • 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.
  • M Offline
    M Offline
    MrOplus
    wrote on last edited by
    #1

    hello guys ,
    i have a class named MyClass like this :

    #ifndef MYCLASS_H
    #define MYCLASS_H
    
    
    #include <QObject>
    #include "mainwindow.h"
    class MyClass : public QObject
    {
        Q_OBJECT
    public:
        explicit MyClass (QObject *parent = 0);
        static MainWindow * m_main ;
        static void NotifySystem(); 
    public slots:
    };
    
    #endif // MYCLASS_H
    
    

    when i include the Myclass.h in my MainWindow.h the following error appears :

    error: 'MainWindow' does not name a type
         MainWindow * m_main ;
         ^
    

    it's something like Dependency Loop how can i use the MainWindow in other classes ?

    1 Reply Last reply
    0
    • Chris KawaC Offline
      Chris KawaC Offline
      Chris Kawa
      Lifetime Qt Champion
      wrote on last edited by
      #2

      Yes, it's a dependency cycle.

      There is no single answer. The general rule is you model your app like a tree - the top level class instantiates some children, these instantiate some more and so on. The rule is that you never include from above you co that you don't turn a tree into a graph with cycles.
      MainWindow is usually kinda near or at the top so there shouldn't be (m)any things including it.

      When you have a class included in mainwindow and you want to access mainwindow from that class it usually is a sign of bad design. The use of static there only strengthens that belief.
      The tree-like design is that mainwindow instantiates a child (a dialog, a panel, a manager or whatever), runs some methods on it and retrieves some data from it. The child instance should never know about a mainwindow or any parent for that matter. Everything should look downward.

      What's your particular use case here? Maybe we can help you find the right design.

      M 1 Reply Last reply
      2
      • Chris KawaC Chris Kawa

        Yes, it's a dependency cycle.

        There is no single answer. The general rule is you model your app like a tree - the top level class instantiates some children, these instantiate some more and so on. The rule is that you never include from above you co that you don't turn a tree into a graph with cycles.
        MainWindow is usually kinda near or at the top so there shouldn't be (m)any things including it.

        When you have a class included in mainwindow and you want to access mainwindow from that class it usually is a sign of bad design. The use of static there only strengthens that belief.
        The tree-like design is that mainwindow instantiates a child (a dialog, a panel, a manager or whatever), runs some methods on it and retrieves some data from it. The child instance should never know about a mainwindow or any parent for that matter. Everything should look downward.

        What's your particular use case here? Maybe we can help you find the right design.

        M Offline
        M Offline
        MrOplus
        wrote on last edited by
        #3

        @Chris-Kawa thanks for your reply ,
        i have a winapi class which has a CALLBACK function and it should be static (windows rules) in this function i need to update some controls based on callback result , so because callback is static i cant use SIGNAL/SLOT and i have to pass the mainwindows somehow to update it from static method , so how can i implement that without a bad design :D thanks .

        1 Reply Last reply
        0
        • M Offline
          M Offline
          MrOplus
          wrote on last edited by
          #4

          i have used the forward declaration to fix the error but it's not standard i'm looking for true way not hacky way

          A 1 Reply Last reply
          0
          • M MrOplus

            i have used the forward declaration to fix the error but it's not standard i'm looking for true way not hacky way

            A Offline
            A Offline
            ambershark
            wrote on last edited by ambershark
            #5

            @MrOplus said in 'MainWindow' does not name a type:

            i have used the forward declaration to fix the error but it's not standard i'm looking for true way not hacky way

            Forward declaration is not only standard but something you should strive for. It will speed up your builds tremendously. I try to almost never include things in my headers if I can avoid it.

            The second thing here is you are breaking the rules of OOP if you have interdependent objects like that. Having an object use your main window is quite common but having you main window need that same object #include'd as well is quite abnormal.

            So like @Chris-Kawa said it is definitely bad class design/oop. I would fix the design but barring that forward declaration will fix it. You should use forward declaration as much as possible in C++ though. The build speed benefits alone are worth it. :)

            Oh and another potential fix is to not include myclass in your mainwindow.h. You can either forward declare there, or better yet just include it in the cpp. If your mainwindow relies on MyClass and MyClass relies on MainWindow that is the bad design part. An Apple doesn't need to know anything about a Worm but the Worm needs to know about the Apple to eat it. So including Worm in Apple would be bad since they aren't really related even though one can use/work with the other.

            My L-GPL'd C++ Logger github.com/ambershark-mike/sharklog

            1 Reply Last reply
            3
            • Chris KawaC Offline
              Chris KawaC Offline
              Chris Kawa
              Lifetime Qt Champion
              wrote on last edited by Chris Kawa
              #6

              For C like apis (WinApi being an example) you usually create a wrapper class. That wrapper's sole purpose is to wrap the foreign api. It should not mangle with MainWindow. It can emit signals that MainWindow chooses to connect to. This way only MainWindow (higher in the tree) knows about a wrapper (includes it). A dumb wrapper can look like this:

              class WinAPiWrapper : public QObject {
                  Q_OBJECT
              public:
                  WinAPiWrapper(QObject* parent = nullptr) : QObject(parent) { instance = this; }
                  ~WinAPiWrapper() { instance = nullptr; }
              
              public slots:
                  void CallSomeWinapi(int param, int param2) {
                      WinApiFunc(param, param2, WinapiCallback);
                  }
              
              signals:
                  void SomeWinapiFinished(int ret_param) const;
              
              private:
                  static void WinapiCallback(int ret_param) {
                      if (instance)
                          emit instance->SomeWinapiFinished(ret_param);
                  }
              
                  static WinAPiWrapper* instance;
              };
              

              Of course it doesn't follow the rules of a good singleton for brevity. Make necessary adjustments.

              Some callbacks are nicer than others. The nicer ones have a void*or similar pointer for user data. This is often used to pass the this pointer to them and get it back in the callback. With such callbacks you don't even need a singleton solution:

              class WinAPiWrapper : public QObject {
                  Q_OBJECT
              public:
                  WinAPiWrapper(QObject* parent = nullptr) : QObject(parent) {}
              
              public slots:
                  void CallSomeWinapi(int param, int param2) {
                      WinApiFunc(param, param2, WinapiCallback, this); //assuming the last param is the void* user data
                  }
              
              signals:
                  void SomeWinapiFinished(int ret_param) const;
              
              private:
                  static void WinapiCallback(int ret_param, void* user_data) {
                      WinAPiWrapper* instance = reinterpret_cast<WinAPiWrapper*>(user_data); //get back the instance pointer from user data
                      emit instance->SomeWinapiFinished(ret_param);
                  }
              };
              
              1 Reply Last reply
              3
              • M Offline
                M Offline
                MrOplus
                wrote on last edited by
                #7

                thanks everyone for your helps that's exactly what i want .

                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