Important: Please read the Qt Code of Conduct -

Defining inner classes not directly in declaration

  • Hello,

    I've got a basic question, I'm a little confused how to solve this:
    I have a class "main_window" with a few Widgets:
    @class main_window : public QWidget
    QHBoxLayout* layout_1;
    QHBoxLayout layout_2;
    QTableWidget* table_1;
    QTableWidget table_2;



    layout_1 = new QHBoxLayout();
    table_1 = new QTableWidget();
    // how do I create the non-pointer widgets layout_2 and table_2 now??
    I don't know how to initialize non-pointer widgets like layout_2 and table_2... can anybody help me with that?

  • Moderators

    They are default initialized i.e. a parameterless constructor is called automatically for them. If that's ok then you don't need to do anything more to initialize them.

    If you want to call a constructor variant that takes parameters you can do that in the initialization list, for example:
    main_window::main_window() : layout_2(this), table_2(1,1,this)
    layout_1 = new QHBoxLayout();
    table_1 = new QTableWidget();

  • Hi,
    thank you for your fast reply!
    The problem with that is, that I'd like to create an instance of window main like this:
    @class main_window : public QWidget
    QHBoxLayout layout;
    QTableWidget table;
    QTextEdit textedit;
    QPushButton pushbutton;
    // and so on...

    void createContent(const QString &content);

    int main(int argc, char** args)
    window_main window_1, window_2;
    ... and later, when I decided what kind of window it is and what it should contain, I'd like to create instances of it's members:

    void window_main::createContent(const QString &content)
    if(content == "button")
    // --> then creating instance of QPushButton
    else if(content == "textedit")
    // --> then creating instance of QTextEdit
    Using the variant with pointers and dynamic instance creation, I can do it like that and the program doesn't consume that much memory because it doesn't create all members automatically...
    Is there a way to do it with variant 2 (static without pointers/heap memory) ?

  • Moderators

    It's exactly like "int i;" You can't create i later.It's already there.
    So no, when you have non-pointer members they are all instantiated as part of your class creation. You can't "create" them later. They are already there.

  • Ok, that is what I also guessed.
    So which variant would you prefer? In cases like this, working with classes that include lots of other classes, should I use pointers or directly initialization? After googling for a while I heard some people say that dynamically creating objects with new/delete should only be used if it is really needed (scope aspect) because of heap usage, missing GC, error capturing in case of memory allocation failure etc...

    What do you mean?

  • Moderators

    I'd say that, as to all questions of such large scope, the only possible answer is: it depends.
    I mean it's great to listen to stories and opinions of others, but the real reason for this is so that you can make an informed decision for your own design. For example if someone says "avoid heap at all costs" and you're working with transmitting 1GB blocks of data how are you suppose to do that? You'll go mad trying. Another person tells you that you should put as much abstraction, templates and whatnot so that your code is clean and easy to read. Sounds great! But then you have to work with a small embedded system that can't really afford all those virtual functions or a codebase of the size of facebook that takes another 20 minutes just to compile that one more template. Another one says new is slower than stack variable. Why would you care about calling a single new on a machine with 4GHz processor and 8Mb of cache and giant memory bus if it's inconvenient and makes code harder to read in that case? It all depends.

    What I'm trying to say by this long rant is: Figure out what your priorities and goals are. Figure out what are the constraints on these priorities. Look for techniques and design patterns that allow you to achieve these goals. Know what is the bottleneck. Is it memory bandwidth, cpu intense calculations, slow I/O, development or compilation time, maintenance, testing ability etc. It's best to follow guidlines that have been tasted by thousands of others but if you have a good reason to break any don't be afraid. Just know why and what it costs.

    Having said that I don't know your app and what its goals are, so take my advice with a grain of salt. From the fragment you mentioned I wouldn't go for any of these solutions. It seems that your widget doesn't know ahead what it's going to host so semantically there's no relation to either pointers or non-pointer members. What I would do is create an interface in that widget that allows you to add any type of widget as a content eg. setWidget method. This is btw a design that QMainWindow follows with its setCentralWidget method.Then create a separate factory class that will create a different type of content depending on the request eg. createUi(SomeEnum type). On top of these two a manager class that would figure out, with whatever business logic you have, which type of ui you need, call the factory to create that ui and then set it on the widget.
    This design might be perfect for your case or it can be totally unjustified. Again - it depends and it's up to you to make a decision.

    There's no inherent "evil" in using pointers and dynamic allocation, but there are different considerations for different scenarios. Some examples:

    "new is slower than stack variables" - to some extent,yes, but usually that's not an issue at all. Stack is also limited in size and large stack frames can be a real problem in eg. deep recursive calls.

    "if you write new you'll forget delete and leak" a.k.a. "JavaCoder rant: I want my GC ;( " - just use smart pointers and RAII. You'll never have to see new or delete anything manually.

    "new doesn't care about scope" - yes, and often that's exactly what you want

    "new is a gate to null pointer bugs" - yes, c++ is hard and you can shoot yourself in the foot. If you don't check for nullptr when you should then it's your fault and sometimes nullptr is the ideal solution to express optionality in a design.

    "it's easy to leak dynamic memory when using exceptions" - again, smart pointers and RAII or just don't use exceptions. Qt doesn't and it's a great library.

    ...and on and on...

  • Wow, is there a way to like great posts? :)
    Thank you so much, Chris!

    The impression I receive more and more is, that I should (as you told) try it on my own and when I notice that it's wrong the way I try it, then I can change it.
    I'm an absolute newbie in Qt and my little code snippets will never make any memory problems or problems with long compilation time or stuff..
    I know a little more now about when to use the one option and when to use the other one and that it always depends on what I'm doing and on this way, I'll try it on my own.

    Thank's again, great support! :)

    It's also interesting that Qt Designer only uses the dynamic method :-P

Log in to reply