0

Say I have two classes like so:

controller.hpp (included by controller.cpp)

#include "testing.hpp"
class controller
{
    public:
        testing _testing;  // call constructor
}

testing.hpp

class testing
{
    public:
        testing();
        ~testing();
}

How do I call the destructor of testing and re-construct it from controller.cpp? Thank you.

xinthose
  • 3,213
  • 3
  • 40
  • 59
  • 5
    `_testing = testing();` – LogicStuff Dec 14 '16 at 14:43
  • 3
    You don't need to. It happens automatically when an instance of the `controller` class is created! If you want to call something other than the default constructor, use a [member initialization list](http://stackoverflow.com/questions/926752/why-should-i-prefer-to-use-member-initialization-list) in the `controller` class's constructor. – Cody Gray - on strike Dec 14 '16 at 14:46
  • @LogicStuff Thank you. That gives me a whole bunch of errors about Boost deleted function on my atomic variables. What about calling `testing _testing;` again? – xinthose Dec 14 '16 at 15:23
  • 1
    @xinthose That's a data member declaration. Look for the fix for your errors. You probably need a move constructor. – LogicStuff Dec 14 '16 at 15:27
  • @LogicStuff OK. How would I use a move constructor in this case? I use atomic bools like so in the `testing` class: `boost::atomic atomic_var {false};` Would it be `testing _testing1;`, `_testing = std::move(testing1)`? – xinthose Dec 14 '16 at 15:40

3 Answers3

2

You usually don't explicitly call the destructor. It is call automatically when the object is destroyed. When an object is created on the stack, the destructor is called automatically when the object goes out of scope. When an object is created on the heap (by new'ing it), the destructor is called automatically when delete is called on the object.

zooropa
  • 3,929
  • 8
  • 39
  • 61
  • There is a case when destructors are called explicitly. – SergeyA Dec 14 '16 at 14:45
  • Good point, Sergey. Thanks for the comment. I made an edit to reflect your comment. One does not usually call the destructor. Like you mentioned, the destructor can be called. The question xinthose asked is not clear why the destructor would need to be called explicitly. That's why I answered the way I did. – zooropa Dec 14 '16 at 14:52
2

I think, you totally misunderstand the idea of default constructors. The main idea is that you almost never call default constructor explicitly (absent placement new). Ditto for destructors. So in your case, testing constructor will be called automatically whenever controller object is created, and it it's destructor will be called whenever controller object is destroyed.

SergeyA
  • 61,605
  • 5
  • 78
  • 137
  • Thank you. I do not want to call the destructor on `controller` because it runs my main code. So I will need to initialize the `testing` object outside of the header file I think. – xinthose Dec 14 '16 at 14:50
1

In your code a controller owns a testing. The implication to anyone reading the code is that it is the same testing for the lifetime of the controller. This is certainly also how C++ see it - it will construct the testing during construction of a controller and destroy the testing when the controller is destroyed.

Two possible solutions:

  1. Instead of trying to replace testing, reset it. This is what @LogicStuff was talking about in his comment on your question. _testing = testing(); constructs a new testing and then copies its state to the existing instance, making the exisiting instance look like a new one. You could (should?) make this explicit by giving testing a Reset method (whose implementation should typically be that assignment *this = testing(); rather than a hand-coded resetting of each member variable.) - Do this only if resetting a testing makes business sense.
  2. If resetting testing doesn't make sense on a business level, and you are in fact wanting to replace it, then have controller own a std::unique_ptr<testing> instead. Then you can reset or swap a newly constructed instance in whenever you need to and still be sure that destructors will be called automatically.
Allison Lock
  • 2,375
  • 15
  • 17
  • I agree. Thank you. How would the code look? `std::unique_ptr _testing (new testing);`? – xinthose Dec 14 '16 at 16:39
  • Nvm; `std::unique_ptr _testing` compiles. Variables and functions are accessived via `->` and not `.` anymore. Now I need to figure out how to use this with `boost::thread thr (boost::bind(&testing::func1, &_testing));` – xinthose Dec 14 '16 at 16:49
  • Turns out I need to use a `shared_ptr` for that operation (safer than unique_ptr): http://stackoverflow.com/a/28823025/4056146. I'm using Boost 1.55 (Debian 8 repo), which doesn't have `unique_ptr` anyway. – xinthose Dec 14 '16 at 17:02