views:

434

answers:

5

I have a class with a (non smart) pointer to an interface object (lets call it pInterface) and I am building a nested class which also needs access to that interface. I am going to get around this by passing the pointer to the interface into the constructor of the nested class like so:

CNestedClass someClass( pInterface, ... );

However I am unsure of the best way of storing this pointer in the nested class. I could use:

1) A scoped (or other smart) pointer (to the original object)
2) A pointer to a pointer

What would you guys suggest and why?

EDIT: I should clarify - the nested class will need to call methods on the interface object, however it does not create it (or modify the object 'pointed' to ), the parent class is responsible for that.

+1  A: 

Pass in the address of a pointer to your interface (IMyInterface**ppInterface), and fill the pointer if it is implemented by the class.

The class can cast its this pointer to that interface and fill in the pointer *ppInterface. If the class does not implement this interface it can set *ppInterface to NULL.

Brian R. Bondy
+5  A: 

The use a pointer to a pointer is if either class may alter the value of the pointer - e.g. by deleting the existing object and replacing it with a new one. This allows both classes to still use the same object by dereferencing the pointer-to-pointer.

If not your concern is ensuring the object remains valid throughout the lifetime of both classes.

  • If the nested class lives shorter you don't really have to worry.
  • If it's the same, provided you clean-up in the correct order (e.g. nested class first, object later) then again, you don't have to worry
  • If the nested class could persist after the owner is destroyed then you must implement a way to ensure the object also persists.

If you need to ensure the lifetime of the object it could be done via reference counting-semantics, either manually or through a smart-pointer interface.

For a smart pointer then boost::shared_ptr would be a good choice. shared_ptr allows the ownership of an object to be shared amount multiple pointers. When the last shared_ptr goes out of scope, the object is deleted.

(note this is not the case with auto_ptr, where an object are exclusively owned).

Things to be aware of;

  1. When using boost::shared_ptr be sure the nested class has a copy of the shared_ptr and not a reference/pointer.
  2. std::auto_ptr behaves quite differently, objects are exclusively owned and not shared
  3. boost::shared_ptr can only work with heap objects, e.g pointers returned from a call to 'new'

Example:

typedef boost::shared_ptr<Interface> shared_interface;

class NestedClass
{
  shared_interface mInterface; // empty pointer
}

void NestedClass::setInterface(shared_interface& foo)
{
  mInterface= foo; // take a copy of foo.
}

void ParentClass::init( void )
{
  // mInterface is also declared as shared_interface
  mInterface = new Interface();
  mNestedClass->setInterface(mInterface);
}
Andrew Grant
Could you elaborate further ? If I use a smart pointer, presumably it would be a good idea to use a shared pointer in both the parent and nested classes?
Konrad
I agree that the only concern is that it should remain valid. But other methods are available depending on ho wthe child is used. (Example: If the child lifespan is guranteed to be shorter than the parent (then pass a reference)).
Martin York
+1 reference. Many of the other answers deal with pointer to pointer where references are much better suited.
David Rodríguez - dribeas
Why are references better suited? They are basically pointers with a sugary syntax. They also have restrictions that may make them unsuitable - for example if the OP wishes NULL to be a valid value for the interface.
Andrew Grant
A: 

Basically, you are sharing a pointer to the same object between two different objects. If you are not using any smart pointers, simply store the pointer to the shared object. You must be careful about ownership of the shared object, i.e. which object is responsible to deallocate the shared object and notify the others that it's gone.

m-sharp
+2  A: 

The other reason you may want to use a pointer to a pointer would be if the outer code might change the original pointer value (e.g. make it point to a new object, or set it to NULL after releasing the object it points to). However, IMO it is quite bad practice to change a pointer after giving it to someone else.

So, if neither the outer code nor the nested class changes the pointer, just store it in the nested class as a copy of the original pointer as a member variable (field).

Duckboy
A: 
class Outer
{
    class Inner
    {
    };
};

As an object of Outer only holds a RAW pointer to a pInterface object this implies that the Outer object does not own or have any control over the lifespan of the pInterface object. We therefore hope there is some guarantee that the pInterface object will live as long as the outer object; In this case there is no reason to even use a pointer you could just use a reference (assuming there is no situation that pInterface would be NULL).

How Inner holds its 'reference' (not C++ reference) depends and really we need more information about the relationship between the objects involved!

  • What is the realationship between Inner and Outer objects.
  • What is the lifespan of an Inner object in relation to the Outer object that it inherited the pInterface pointer from?
  • What is the guarantee that an Outer object has a lifespan shorter than a pInterface object.

etc.

Martin York