1

I noticed that my Member initializer list is not really readable.

My main.cpp files looks like this:

#include "Application.hpp"

using Pathfinding::Core::Application;

int main() 
{
    Application app;
    app.run();
    return 0;
}

Constructor of Application class looks like this:

    Application::Application()
        : window(sf::VideoMode(GRID_FIELD_WIDTH + MENU_WIDTH, GRID_FIELD_HEIGHT), APPLICATION_TITLE, sf::Style::Titlebar | sf::Style::Close),
          graph(GRID_FIELD_HEIGHT / appState.currentNodeSideLength(), GRID_FIELD_HEIGHT / appState.currentNodeSideLength()),
          eventManager(&window),
          menu(&appState, GRID_FIELD_WIDTH, GRID_FIELD_HEIGHT, MENU_WIDTH),
          dstar(&graph),
          graphOps(&graph, appState.currentNodeSideLength())
    {
      ...
    }

The only thing I can think of is to instantiate all the objects from the initializer list in main.cpp and pass them to the Application. Application will still have the same number of elements in the member initializer list but the constructor arguments are gone which will look like this:

    Application::Application(sf::RenderWindow * window_, 
                             LatticeGraph * graph_, 
                             EventManager * eventManager_, 
                             Menu * menu_, 
                             DStarLite * dstar_, 
                             GraphOperations * graphOps_)
        : window(window_),
          graph(graph_),
          eventManager(eventManager_),
          menu(menu_),
          dstar(dstar_),
          graphOps(graphOps_)
    {
      ...
    }

Which of these two aproaches is better? Am I violating some principles in my first aproach? Maybe the first aproach is acceptable?

1
  • 2
    Do you have to perform the initialization explicitly via the constructor? Or could you provide a default member initializer when the member is declared? At least for some members where this would always be a reasonable default? An alternative might be something like solution #2, but assembling the parts in a public static member function (not in the main() function!). Such factory functions can also be called from your default constructor, leading to delegated constructor fun like Application::Application() : Application(Application::make_app()) {}
    – amon
    Jan 22 at 13:55

1 Answer 1

4

Just write the version that inspires you most. You can always refactor afterwards.

The first version has the advantage that it fits the immediate needs. The inconvenience is that it hardwires Application by coupling it to some global objects (hidden dependencies). This reduces the reusability and requires to know about the internals of that class.

The second version has the advantage of flexibility: the client (main()) could first load a configuration file for user personalisation. Or you could decide to launch several applications in independent windows with independent menus. Or it could use some more specialized classes for them. It promotes reusability. But the inconvenience is that it puts more responsibilities on the client.

A third version could mix both: a builder could create the needed objects and assemble then assemble the Application in the end. This would keep Application flexible, and keep responsibilities of the client very low. For an application class this seems however overkill.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.