Qt World Summit: Submit your Presentation

Question about the ui_class name.h file

  • I have a Qt widget project called "SeasonCreator" and am wondering about the structure of a Qt widget project.

    The ui_seasoncreator.h file is hidden, but when you look into it, it defines a namespace called "Ui" and in it is a declaration of a class SeasonCreator, which inherits from Ui_SeasonCreator, which is the c.

    In the seasoncreator.h file, there is also a namespace called "Ui" also with a declaration of a class called "SeasonCreator". When I click to find its original declaration it leads me to the declaration of Ui::SeasonCreator in the ui_seasoncreator.h file.

    What is the purpose for these namespace and classes? Do the two definitions relate?

    Do any of these Ui::SeasonCreator declarations have anything to do with the custom SeasonCreator class in seasoncreator.h?

  • The "ui_xxx.h" files are created from your .ui files (QtDesigner files). They declare and implement all the abstract actions you have taken in QtDesigner to form your window, i.e. it places buttons, sets captions, adds layouts etc.
    If you don't use QtDesigner, you'd have to write all this C++ code yourself, create all widgets yourself one by one. QtDesigner and qmake automate this for you most of the time and the result is that you have those additional code files in your project directory.

    The Ui::SeasonCreator in your seasoncreator.h does indeed relate to the class defined in the ui_ header. It's called a forward declaration (google it if unclear) and is needed, because your SeasonCreator class owns a pointer:
    Ui::SeasonCreator *ui;
    in the private section. What's that good for? Well that allows you to access the ui widgets via that pointer called "ui".

  • Moderators

    [quote author="DerManu" date="1344929341"]you'd have to write all this C++ code yourself[/quote]

    Just a small correction here - you don't HAVE to write it in c++, you can also write XML .ui file by hand ;) Although using QtDesigner (it's oart od QtCreator, if you are wondering) is simpler and faster.

    .ui files are converted into headers by a tool named "uic", which is invoked automatically by qmake.

  • So is the Ui::SeasonCreator class in seasoncreator.h just a redeclaration of the class in ui_seasoncreator.h? Or is it declaring the custom SeasonCreator class?

    I do not see how it is a foward declaration.

    Thanks for the help so far.

  • Moderators

    After you compile your project, you can take a look at ui_classname.h, it's a standard C++ header file. That should clear things up.

  • When I compile the project, ui_classname.h does not seem to change at all. It looks like a pretty standard header file from the start.

  • [quote author="Flurite" date="1344950783"]So is the Ui::SeasonCreator class in seasoncreator.h just a redeclaration of the class in ui_seasoncreator.h? Or is it declaring the custom SeasonCreator class?
    I do not see how it is a foward declaration.

    The Ui::SeasonCreator in seasoncreator.h is a forward declaration of the class in ui_seasoncreator.h. The forward declaration is needed, because your main window class ("SeasonCreator") has a pointer member to an instance of Ui::SeasonCreator in its private member section named "ui", as mentioned before. If we wouldn't forward declare that class type, the compiler would complain that this type isn't known.
    As with all forward declarations, the code file where the Ui::SeasonCreator class is actually used needs not only a forward declaration, but the actual definition of the class included. And tadaaa, the seasoncreator.cpp includes ui_seasoncreator.h, correct? That's because in seasoncreator.cpp you actually want to access functions and members of the "ui" pointer, and not just declare it as in the seasoncreator.h.
    It would have been almost equivalent if we just include the ui_ header in the seasoncreator.h and thus wouldn't need the forward declaration. But it's good style to keep dependencies at a minimum, and this way any other code file that includes seasoncreator.h doesn't get the burden of also including ui_seasoncreator.h, but only sees (and needs) the forward declaration.

  • Thanks, I think I'm starting to get it.

    Technically, the declaration in seasoncreator.h is probably called a foward declaration, but can it (Ui::SeasonCreator in ui_seasoncreator.h) also be considered a redeclaration of a class to introduce it into the seasoncreator.h?

  • A forward declaration is not a re-declaration because the type name that is being forward declared hasn't been declared or defined yet. That's the whole point.
    There is no re anywhere here. Also the declaration (via definition) of the class in its header (ui_seasoncreator.h) is in that sense not a redeclaration because it doesn't know about the forward declaration. On a side note: "Redeclaration" usually refers to a compiler error where you use the same identifier for two different things or define the same class multiple times.

    What you could say is that it's just a declaration without definition. Thus the compiler is happy if only references (pointers) are used in that context, at least until he gets a full definition of the class. But just calling it a "declaration" might confuse the intent of the programmer, so one uses the more specific term and adds a "forward".

  • Aren't there two definitions of the Ui namespace though? Within each of them is a SeasonCreator class. That's the part that confuses me. seasoncreator.h somehow has access to ui_seasoncreator.h and the former does not include the latter. That's what led me to believe they were different, but they are same.

    Is there only one namespace (of a signature, in this case Ui) in the global scope and it can be declared anywhere?

  • Moderators

    Let's approach forward declaration from a different angle, maybe it will be easier there. It's actually used a lot to speed up compilation. Imagine you have a simple class:
    class Simple {
    /* some code */

    QString *myString;


    Now, since this QString is a pointer, all the compiler needs to know at this point is that there is as class named "QString". It does not need to know anything about the actual implementation of QString class. That is why we can forward-declare it, like this:
    class QString;

    class Simple {
    /* some code */

    QString *myString;


    No include is needed at that point, and the compiler is happy to swallow it. Then, in the .cpp file, where you instantiate the object behind the pointer, our compiler needs to know what the details are - because it has to allocate the memory, and call relevant methods (constructor, etc.). So, in our source file, we have this:
    #include <QtCore/QString>
    #include simple.h

    void Simple::Simple() {
    myString = new QString("Forward-declared!");

    Hope this helps in understanding, even though it tackles a bit different issue. BTW, forward declaration is really useful in optimising compilation (If you use just QString in your class, there is no need to include the whole QtCore module in the header, just the QString in .cpp file. In recent optimisation job I did, it sped up compilation time from 5 minutes to about 3 minutes).

  • I understand that. I just do not see how two declarations of the Ui namespace (and the SeasonCreator class within it) would work.

    In seasoncreator.h there is a Ui namespace with a SeasonCreator class. When I ctrl->click the name of the namespace or class, it brings me to another namespace named Ui with a class called SeasonCreator in it. This is what makes me think there are two declarations.

  • Namespaces can live in multiple files without trouble. See the namespace as a literal addition to the type name. You forward declare Ui::SeasonCreator wherever the compiler only needs to know that such a type exists and doesn't need any more details about the class, and somewhere else (in the ui_seasoncreator.h file) give the full Ui::SeasonCreator definition. Works as intended.

    bq. I understand that. I just do not see how two declarations of the Ui namespace (and the SeasonCreator class within it) would work.

    But then I don't think that you actually understand it... Forward declaration is harmless, you can do it multiple times without conflicting:
    @class A; // forward declaration
    class A; // Another one...
    class A; // Yet another one!
    class A; // Does it ever stop?
    class A {...}; // Ah finally, the definition.
    class A {...}; // Uh oh, this won't work. Definition can only happen once.@

  • Makes sense now.

    Thank you two very much!

Log in to reply