In a small game I'm writing, I have a class Weapon
with two constructors, one which takes in some parameters to produce a custom weapon, and one that grabs a default one (the CHAIN_GUN
):
Weapon::Weapon (void) { // Standard weapon *this = getWeapon(CHAIN_GUN); return; }
Question: Are there any negative consequences from using *this
and operator=
to initialise a class?
Some people feel you should not use the this pointer in a constructor because the object is not fully formed yet. However you can use this in the constructor (in the { body } and even in the initialization list) if you are careful.
There are two ways to initialize a class object: Using a parenthesized expression list. The compiler calls the constructor of the class using this list as the constructor's argument list. Using a single initialization value and the = operator.
zero-initialization – Applied to static and thread-local variables before any other initialization. If T is scalar (arithmetic, pointer, enum), it is initialized from 0 ; if it's a class type, all base classes and data members are zero-initialized; if it's an array, each element is zero-initialized.
Why constructors are efficient instead of a function init() defined by the user to initialize the data members of an object? Explanation: We cannot use init() because as mentioned in options that user may forget to initialize the members which will lead to a segmentation fault.
Imagine that someone asked you to draw a painting... would you;
- first draw your default (1st) (that familiar smilie face you like so much),
- then draw what that someone asked for (2nd),
- only to draw the same thing one more time, but on the canvas containing your default,
- and then burn the 2nd painting?
This post will try to explain why this simile is relevant.
WHY IS IT A BAD IDEA?
I've never seen a default-constructor implemented with the use of the assignment-operator, and honestly it's not something that I'd recommend, nor support during a code review.
The major problem with such code is that we are, by definition, constructing two objects (instead of one) and calling a member-function, meaning that we construct all our members two times, and later having to copy/move initialize all members by calling the assignment operator.
It's unintuitive that upon requesting construction of 1 object, we construct 2 objects, only to later copy the values from the 2nd to the 1st and discard the 2nd.
Conclusion: Don't do it.
( Note: In a case where Weapon
has base-classes it will be even worse )
( Note: Another potential danger is that the factory function accidentially uses the default-constructor, resulting in an infinite recursion not caught during compilation, as noted by @Ratchet Freat )
PROPOSED SOLUTION
In your specific case you are far better off using a default-argument in your constructor, as in the below example.
class Weapon { public: Weapon(WeaponType w_type = CHAIN_GUN); ... }
Weapon w1; // w_type = CHAIN_GUN Weapon w2 (KNOWLEDGE); // the most powerful weapon
( Note: An alternative to the above would be to use a delegating constructor, available in C++11 )
Using the assignment operator to implement a constructor is rarely a good idea. In your case, for example, you could just use a default parameter:
Weapon::Weapon(GunType g = CHAIN_GUN) : // Initialize members based on g { }
In other cases, you might use a delegating constructor (with C++11 or later):
Weapon::Weapon(GunType g) : // Initialize members based on g { } Weapon::Weapon() : Weapon(CHAIN_GUN) // Delegate to other constructor { }
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