How to prevent the use of class members not yet built?

I have the following classes:

class A { public: A() { x = 0; std::cout<<"A default ctor()\n"; } A(int x_) { x = x_; std::cout<<"A normal ctor()\n"; } int x; }; class B { public: B() { std::cout<<"B ctor()\n"; } private: std::string str; }; 

and a function that creates object B, taking object A as a parameter:

 B createB(const A& a) { std::cout<<"a int: "<<ax<<"\n"; return B(); } 

if I create a class C that has elements of type A and B, and constructs a B-object before the A-object is built , but using the A object for this , it will compile without warning, but it will silently introduce an error:

 class C { public: C(): b(createB(a)), a(10) {} private: B b; A a; }; int main() { C c; return 0; } 

Of course, the above example is trivial, but I saw it in the real world, in a much more complex code (this is Friday, 8:30 pm, and I just fixed this error, which led to segfaults).

How can I prevent this?

+4
source share
2 answers

I agree with what others have suggested, namely that the burden on the designer is to ensure that the objects are initialized before use. I see two ways to do this in your case:

First (and easiest), reorder a and b in the class definition:

 class C { public: C(): b(createB(a)), a(10) {} private: A a; B b; }; 

Secondly, you can move a to the base class if you really want to emphasize that its initialization occurs earlier than other members:

 class CBase { protected: CBase(): a(10) {} protected: A a; }; class C : private CBase { public: C(): b(createB(a)) {} private: B b; }; 
+2
source

I see three possible options:

Require A to build before building C :

 class C { public: C(const A& a) : a_(a), b_(a) {} private: A a_; B b_; }; 

Build A to build "B":

Completion of construction B to completion A This stops undefined behavior, but does not provide proper behavior through the interface (as options 1 and 3 do)

 class C { public: C() : a_(/* construct as appropriate */) { b_.reset(new B(a_)); } private: A a_; std::unique_ptr<B> b_; }; 

If the design allows this, B contain (and expose) A

This seems possible from a trivial example, but in real life it may not be:

 class B { public: const A& my_a() {return a_;} private: // construct as appropriate (?) A a_; }; class C { private: B b_; }; 
0
source

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


All Articles