How to use links, avoid heading bloat and delay initialization?

I was looking for an alternative to using so many shared_ptrs and found a great answer in the comments section:

Do you really need a joint ownership? If you stop and think about a few minutes, I’m sure that you can precisely determine one owner of the object and a number of users who will use only this during the life of the owner. So just make it a local / member owner object and pass links to those who should use it.

I would love to do this, but the problem is that defining the owner object now requires that the object that needs to be fully defined is fully defined. For example, let's say I have the following in FooManager.h:

class Foo; 
class FooManager
{
    shared_ptr<Foo> foo;
    shared_ptr<Foo> getFoo() { return foo; }
};

Now, taking the advice above, FooManager.h becomes:

#include "Foo.h"
class FooManager
{
    Foo foo;
    Foo& getFoo() { return foo; }
};

I have two problems with this. Firstly, FooManager.h is no longer easy. Each cpp file that includes it should now also compile Foo.h. Secondly, I no longer need to choose when foo is initialized. It must be initialized simultaneously with FooManager. How do I get around these issues?

+3
source share
3 answers

You can use shared_ptr(or any smart pointer, or even a dumb pointer), but not have sharing.

eg.

class Foo; 
class FooManager
{
  private:
    shared_ptr<Foo> foo;
  public:
    Foo& getFoo() { return *foo; }
};

( - setFoo(), , , getFoo() Foo *. , , , foo.)

+3

shared_ptr, .

, ( ), boost::scoped_ptr .

Boost, scoped_ptr - Boost ( boost/shared_ptr.hpp) .

+3

pimpl .

FooManager.h:

class Foo;

class FooManager
{
   struct Impl;
   Impl *m_impl;
public:
   Foo& getFoo();

   FooManager();
   ~FooManager();
};

FooManager.cpp

#include "Foo.h"
#include "FooManager.h"

struct FooManager::Impl
{
   Foo* m_foo;
   int m_someothermember;
   FooManager::Impl() : m_foo(NULL), m_someothermember(0) {}
};

FooManager::FooManager() : m_impl(new FooManager::Impl())
{}

Foo& FooManager::getFoo()
{
   // Lazy initialization
   if( !m_impl->m_foo ) {
      m_impl->m_foo = new Foo;
   }
   return *m_impl->m_foo;
 }

 FooManager::~FooManager()
 {
    delete m_impl->m_foo;
    delete m_impl;
 }

Since you are already using boost, I would recommend using it scoped_ptrto implement this in your real code instead of manually managing memory, as I did in this example. It is important to remember that the declaration works as well as it does for pointers (which is part of the reason it worked for shared_ptr).

+2
source

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


All Articles