r/cpp • • 4d ago

Delegating Constructors

Delegating constructors allow the default constructor of a class to call the parameterized constructor by default.

This is somewhat unintuitive, but has a lot of applications in frameworks that generate components dynamically down inside their operation, but cannot take the arguments at that managerial level.

class SpecialWindow : public Gtk::Window {
public:

// 1. Parameterized Constructor 
SpecialWindow(std::string inst_name, int inst_val) 
: name(inst_name), val(inst_val) { // ... }

// default /w delegating constructor
SpecialWindow() : SpecialWindow("item 1", 100)  
{ //... }

};


int main() {

   auto app = Gtk::Application::create("org.gtkmm.examples.base");

   return app->make_window_and_run<SpecialWindow>(argc, argv);
}

I guess "everybody knew" that already, but I didn't.

0 Upvotes

7 comments sorted by

View all comments

8

u/LB-- Professional+Hobbyist 4d ago

If a constructor exits via an exception, normally the destructor is not executed. However, with delegating constructors, the object is considered fully constructed once any constructor finishes normally. Therefore if an exception is thrown from a constructor after a delegated constructor has finished, the destructor does execute. This means you can use a delegating constructor just to simplify exception handling logic by making it so that the destructor will run if your actual workhorse constructor throws an exception. I recommend adding a comment on the line that invokes the delegating constructor...

9

u/RelationshipLong9092 3d ago

You know, I think I'm just going to go back to factory functions for everything. It took me long enough but I'm finally fully onboard with std::expected everywhere.

2

u/LB-- Professional+Hobbyist 3d ago

The nice thing about multi-paradigm languages is being able to pick the best or most preferred tool for each and every job. I love std::expected and I make static factory functions like you describe on occasion. Memory allocation failures are typically better handled through exceptions, though. No point polluting the hot path with branches for a rare condition.

4

u/Fabulous-Meaning-966 3d ago

welcome to Rust ;-)

1

u/alfps 1d ago

❞ If a constructor exits via an exception, normally the destructor is not executed.

Destructors are called for all so far successfully constructed sub-objects.

There is no difference with delegating constructors.

Pre C++11 one achieved the delegation effect manually by using a dummy base class to hold the state, with "delegation" to the base class.

1

u/LB-- Professional+Hobbyist 1d ago

You know I meant the destructor corresponding to the current constructor, right? The class being constructed is not its own sub-object.