Purpose of general ptrs (boost) in the constructor, unit testing

I have a C ++ class (inside a dll project) whose member variables are boost :: shared_ptrs for objects of other classes. Is it better to assign them inside the class constructor or have a separate init () function that does this.

I accept the default value of a pointer to T inside boost :: shared_ptr is NULL. Therefore, if I do nothing inside the constructor, boost :: shared_ptr get () will return NULL before calling the Init () function.

Besides what happens when there is a problem with allocating memory with a new one in one of the assignment operators, should I catch an exception (in Init) or is it good to tell the calling element Init () to catch this exception? boost :: shared_ptr a (new T);

Are there standard approaches to modeling memory allocation exceptions within unit tests? and make sure all objects are properly selected.

+4
source share
3 answers

I have a C ++ class (inside a dll project) whose member variables are boost :: shared_ptrs for objects of other classes. Is it better to assign them inside the class constructor or have a separate init () function that does this.

As a rule, it is best to do everything in the constructor. Having an init () function called afterwords implies that the object is not valid after building, so you need to save the state flag to indicate whether init () has been called, and check this flag when calling any public method and do somthing suitable for uninitialized object

I accept the default value of a pointer to T inside boost :: shared_ptr is NULL. Therefore, if I do nothing inside the constructor, boost :: shared_ptr get () will return NULL before calling the Init () function.

Yes: the default constructor for shared_ptr initializes it to NULL.

Besides what happens when there is a problem with allocating memory with a new one in one of the assignment operators, should I catch an exception (in Init) or is it good to tell the calling element Init () to catch this exception? boost :: shared_ptr a (new T);

If you have a constructor: then all the members that were built will be destroyed correctly (via the destructor), while unified objects will not be affected, and the memory for the current object will be released as if it had not been allocated (Another good reason to use an initialization list).

If you use init (): then you must catch an exception to clear the object correctly and free up memory. Depending on how complex the object is, you can do it inside init (but it's hard to do it right), or the caller must do it. After that, you should do the same as if the exception were thrown from the constructor (it depends on usage).

Are there standard approaches to modeling memory allocation exceptions within unit tests? and make sure all objects are properly selected.

You can use the factory object to highlight objects.
You pass the factory object to the constructor. When you want to simulate an exception at build time, just pass the mock factory that throws this corresponding exception.

+2
source

Use initializer lists to assign members. They are preferred (and sometimes the only approach).

If a problem occurs during object creation, throw an exception and exit it. Or you will need to maintain a valid flag, which you will need to check each time a member function is called to verify that a valid object is valid.

You can always catch exceptions and report it. If the deletion fails, ideally you should not throw an exception, but handle it in dtor, report it and move on.

+1
source

In the first question, you should ideally use initializer lists to ensure that your pointers are valid. Not doing this means that you potentially need to always check if your pointer is valid before using it; especially if you leave it up to the calling code to call init()

On the other hand, maybe you can’t do this if they can only be installed by calling a pure virtual one, in which case you will have to use the init() method.

Upon initialization, I would think that you can either catch, or throw, or simply not catch. In any case, it would be preferable if the caller would throw a memory allocation exception.

I see why you want to try to eliminate memory allocation when calling init() on one of your objects. The approach here may be to replace a stub object that always calls init()

I don’t understand why you want to check the release of shared pointers (possibly raw pointers). Of course, the point with common pointers is that although you can refer to a common pointer that you, by definition, share it so that it is not destroyed yet.

Perhaps you can check the number of links or specify your selected object and (when destroyed) clear the semaphore that your test can control. Did I miss something?

+1
source

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


All Articles