I want to ask you for your best practices regarding constructors in C++. I am not quite sure what I should do in a constructor and what not.
Should I only use it for attribute initializations, calling parent constructors etc.? Or might I even put more complex functions into them like reading and parsing configuration data, setting up external libraries a.s.o.
Or should I write special functions for this? Resp. init()
/ cleanup()
?
What are the PRO's and CON's here?
I figured out yet that for example I can get rid of shared pointers when using init()
and cleanup()
. I can create the objects on the stack as class attributes and initialize it later while it is already constructed.
If I handle it in the constructor I need to instantiate it during runtime. Then I need a pointer.
I really don't know how to decide.
Maybe you can help me out?
A constructor must be called. You can not force the user to use any other function (except the destructor), only by convention.
So yes, doing a lot in constructor is a bad idea in my opinion. Generally I just put some field initializations into the constructor and make an init method to invoke when everybody is on board. I think that your problems may have been caused by violation of SRP and not the constructor doing actual work. – Emily L.
Rules to be rememberedA constructor does not have return type. The name of the constructor is same as the name of the class. A constructor cannot be abstract, final, static and Synchronized. You can use the access specifiers public, protected & private with constructors.
The most common mistake to do in a constructor as well as in a destructor, is to use polymorphism. Polymorphism often does not work in constructors !
e.g.:
class A { public: A(){ doA();} virtual void doA(){}; } class B : public A { public: virtual void doA(){ doB();}; void doB(){}; } void testB() { B b; // this WON'T call doB(); }
this is because the object B is not yet constructed while performing the constructor of the mother class A... thus impossible for it to call the overriden version of void doA();
class A { public: void callAPolymorphicBehaviour() { doOverridenBehaviour(); } virtual void doOverridenBehaviour() { doA(); } void doA(){} }; class B : public A { public: B() { callAPolymorphicBehaviour(); } virtual void doOverridenBehaviour() { doB() } void doB(){} }; void testB() { B b; // this WILL call doB(); }
This time, the reason behind is: at the time the virtual
function doOverridenBehaviour()
is invoked, the object b is already initialized (but not yet constructed), this means that its virtual table is initialized, and thus can perform polymorphism.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With