Class member without default constructor

Suppose I have a class A without a default constructor, a factory factoryA method that returns an object of type A and a class B that has A as a member. I know that in this case, a type A member from B should be initialized in the initialization list of constructor B. I don’t quite understand why, if someone could explain this to me, that would be great. Also, what if the constructor parameter A must be computed inside constructor B, for example, by querying a database or something like that? Is there a way to use the setting below without providing A to the default constructor? Thank you in advance.

class A { private: int _i; public: A(int i) : _i(i) {} }; A factoryA(bool b) { if(b) return A(1); else return A(2); } class B { private: A _a; public: B(int j) { if(j > 0) _a = factoryA(true); else _a = factoryA(false); } }; 
+4
source share
3 answers

Member objects are always initialized before entering the body (the part between curly braces) of the constructor. If you do not specify a member in the initializer list, it will be created by default. So mention it!

 B::B(int j) : _a(factoryA(0 < j)) { }; 

This calls the factoryA function with the argument true if j greater than 0 and false otherwise, and initializes the _a member with the value returned by this call.

+5
source

It’s not entirely clear to me why this is so if someone can explain that it would be great for me.

For classes [*] string _a = factoryA(true); calls _a.operator=(factoryA(true)) . Calling a member function on _a requires that _a already initialized. Therefore, if this is not a compile-time error, it will still be invalid.

Also, what if the constructor parameter A must be computed inside constructor B, for example, by querying a database or something like that? Is there a way to use the setting below without providing A to the default constructor?

As long as A has a copy or move constructor, you can initialize it with the return value of the function, and this function can do anything you like, even using different constructors for A depending on the arguments provided.

 class B { private: A _a; static A getA(int i); public: B(int j) : _a(getA(j)) { } }; AB::getA(int j) { if (j > 0) return factoryA(true); else return factoryA(false); } 

[*] I know there are exceptions.

+4
source

In this case, it is better to use a pointer to A, i.e. A * _a, and then call the constructor anywhere.

0
source

Source: https://habr.com/ru/post/1433096/


All Articles