How to split your main.cpp file into multiples classes



  • Hi,

    I know this may be a c++ question, with relation to inheritance but I'm posting it here since the question involves some Qt slots.

    My mainwindow.cpp file is getting huge and I would like to split it into two classes, so my question is how can I separate three slots from the mainwindow.cpp to its own class?

    I apologize if this is something I should be posting in a C++ forum, but I have learned a lot from this forum that I just come here by instinct.

    This is my current .h file, of course it doesn't contain any code except for the slots I want to move.
    mainwindow.h file:

    @#ifndef MAINWINDOW_H
    #define MAINWINDOW_H
    //#includes here

    namespace Ui
    {
    class MainWindow;
    }

    class MainWindow : public QMainWindow
    {
    Q_OBJECT
    public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

    private slots:
    void on_pushButton_Dxf_clicked();
    void on_pushButton_Pdf_clicked();
    void on_pushButton_Drawing_clicked();

    // more slots here

    private:
    Ui::MainWindow *ui;

    // some functions and variables here
    

    };
    #endif // MAINWINDOW_H@

    Here is my current .cpp file, again it doesn't contain any code except for the slots I want to move.

    mainwindow.cpp file:

    @///#includes here

    MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow)
    {
    ui->setupUi(this);
    }// MainWindow

    MainWindow::~MainWindow()
    {
    delete ui;
    }//~MainWindow deconstructor

    // these are the slots that I want to move to a different class
    void MainWindow::on_pushButton_Dxf_clicked()
    {
    }

    void MainWindow::on_pushButton_Pdf_clicked()
    {
    }

    void MainWindow::on_pushButton_Drawing_clicked()
    {
    }@



  • Could you not simply add #include "mainwindowslots.cpp" where you have the comment "// these are the slots that I want to move to a different class"? I'm not sure if this is best practice, but...



  • Yeah, I guess it was that simple, it worked. I know I know I need some practice with inheritance, but for some reason I thought I was going to need something like.

    @public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();@

    I don't know, I still get confused when I see the code above and some other stuff in Qt that I still don't fully understand.

    Thanks a lot.



  • I suggest keeping together stuff that belongs together - just format your source nicely and use the buttons near the line numbers to collapse or expand areas of the code.

    Although there are no interfaces you can still create abstract or even regular classes and use as interfaces and inherit from them, but this is typically done when you need the same interface in many places, not to save on cpp file size. Things cannot always be kept small and neat - it is not uncommon for cpp files to be many thousands of lines.

    You can significantly clean your class implementation by grouping operations in functions, for example instead of creating 20 buttons one by one in the constructor you write a method that creates the buttons, and in the constructor you call it, so you have only one line and sort of higher level code organization.



  • There is no way to give you advice on how to go about this based on what you post. If what happens in those slots is self-contained, then that might be reason to move that functionality to an object of their own, with a sane API. Any method that longer than, say, what fits on your screen in your editor without scrolling is a candidate for re-factoring though, and if those methods really are as huge as you say, you'd better start with breaking them down first.

    I am not a fan of including C++ implementation files into others to chop an implementation into pieces. I'd rather have that 5kloc class in one go then. Including headers is fine of course, but including sources, though possible, is quite non-standard.



  • Yeah, the main problem is slots will usually have to access class members too, so you either have to explicitly inform the linker for external objects. Even worse, you might be tempted to include the class file to get access to its members and invite a circular dependance issue. At any rate, the potential issues you are inviting is hardly worth the effort, since there is nothing wrong with big cpp files. It is not like you can't fold blocks of code in modern code editors. This is a feature, created for a purpose, use it :)

    Back from the good old C days, the preprocessor allows for some pretty horrendous stuff that you don't necessarily need to be doing just because you can.

    bq. My mainwindow.cpp file is getting huge and I would like to split it into two classes

    Aggregation is a much safer way than including code with the preprocessor, in many cases even preferable to inheritance. Instead of having everything piled together inside your MainWindow, for example if you have a strip of buttons, you can implement a ButtonStrip widget, in which you create the buttons and simply instance the ButtonStrip widget in your MainWindow. Naturally, this will mandate the need of additional interfacing, if all your gui elements are in the MainWindow they have access to each other, whereas with the ButtonStrip widget you will have to do some extra work and add pathways for elements of the ButtonStrip to access elements that are in other "composite" widgets, instanced in MainWindow, e.g. you will have to intercept signals coming from ButtonStrip and forward them to slots, defined in other sub-components.



  • Ok, thank you all for the good advice.

    If this could create me some problems later on I will just put them back.

    [quote author="utcenter" date="1343945550"]It is not like you can't fold blocks of code in modern code editors. This is a feature, created for a purpose, use it :)
    [/quote]

    It would be nice if code editors could save the foldings, that would be awesome.

    I feel bad asking so many silly questions but you guys don't know how much I have learned with your help, even though it doesn't seem like.

    I don't know what would I do without all of the help from this forum.



  • ^^ When I re-open my project with Creator, the regions that were folded are still folded - don't know about other code editors, but Creator seems to properly save folded code blocks.



  • There is no reason a class definition can't be spread over multiple files. The syntax of C++ means the class declaration has to be in a single file but the implementation of the member functions can be spread over as many files as you like.

    I regularly split my MainWindow class into many files each containing a related subset of the whole class. As long as each file includes the class declaration (i.e. the class header file) the compiler takes care of combining all the functions into a single class. I usually get something like this:

    MainWindow.h
    MainWindow.cpp
    MainWindow_actions.cpp
    MainWindow_menus.cpp
    MainWindow_toolbars.cpp

    If the only reason you want to split the class is to make the code more managable then I would just use this multiple file approach and stick with the single MainWindow class.



  • [quote author="utcenter" date="1343977725"]^^ When I re-open my project with Creator, the regions that were folded are still folded - don't know about other code editors, but Creator seems to properly save folded code blocks.[/quote]

    True, I just tried it and it saves your folds, my problem I think is because I'm working between to computers and I usually delete the Tool.pro.user file when exporting from one machine to the other. It would be nice if I could port my settings from one machine to the other.

    [quote author="Swatwork" date="1343987045"]There is no reason a class definition can't be spread over multiple files. The syntax of C++ means the class declaration has to be in a single file but the implementation of the member functions can be spread over as many files as you like.

    I regularly split my MainWindow class into many files each containing a related subset of the whole class. As long as each file includes the class declaration (i.e. the class header file) the compiler takes care of combining all the functions into a single class. I usually get something like this:

    MainWindow.h
    MainWindow.cpp
    MainWindow_actions.cpp
    MainWindow_menus.cpp
    MainWindow_toolbars.cpp

    If the only reason you want to split the class is to make the code more managable then I would just use this multiple file approach and stick with the single MainWindow class.
    [/quote]

    Yes, the only reason I want to split it is as you stated to have subsets of the main class.

    Thank you all for the good advice.


Log in to reply
 

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