Different pointers to same object - behaviour -


#1

Hi,

I am developing a desktop application, and I am using the same “canvas room” to display different graphics depending on the user. So for example I can have 3 different graphics sharing the same space, but I only want to create one object at a time. Every object belongs to different classes.

So:

void resized() override
{
    if(obj1)
		obj1->setBounds(0, 0, getWidth(), getHeight());
	else if(obj2)
		obj2->setBounds(0, 0, getWidth(), getHeight());
    else if(obj3)
		obj3->setBounds(0, 0, getWidth(), getHeight());
}

void buttonClicked(Button* buttonThatWasClicked) override
{
   if (buttonThatWasClicked == bt1)
   {
       obj1 = new A();
       obj2 = nullptr;
       obj3 = nullptr;
   }
   else if (buttonThatWasClicked == bt2)
   {
       obj1 = nullptr;
       obj2 = new B();
       obj3 = nullptr;
   }
   else if (buttonThatWasClicked == bt3)
   {
       obj1 = nullptr;
       obj2 = nullptr;
       obj3 = new C();
   }
}
private:
   ScopedPointer<A>obj1; 
   ScopedPointer<B>obj2; 
   ScopedPointer<C>obj3; 

The inconvenient is that if I finally I design 20 different windows, I would have to create one object and delete all the other 20 times for each button. Since I don’t know which one was the last used.

So I have tried a different approach.

 void resized() override
 {
     current_object->setBounds(0, 0, getWidth(), getHeight());
 }

void buttonClicked(Button* buttonThatWasClicked) override
{
   if (buttonThatWasClicked == bt1)
   {
       current_object = nullptr;
       obj1 = new A();
       current_object = obj1;
   }
   else if (buttonThatWasClicked == bt2)
   {
      current_object = nullptr;
       obj2 = new B();
       current_object = obj2;
   }
   else if (buttonThatWasClicked == bt3)
   {
       current_object = nullptr;
       obj3 = new C();
      current_object = obj3;
   }
}
private:
   ScopedPointer<A>obj1; 
   ScopedPointer<B>obj2; 
   ScopedPointer<C>obj3; 
   Component* current_object;

But if “current_object = obj1” and then I click bt2, “current_object = nullptr” doesn’t delete (or makes NULL) obj1. It does nothing. I mean if b

If I use “ScopedPointercurrent_object” instead of “Component* current_object” I get JUCE pointer errors (free/delete). if “current_object = obj1” and then I click bt2, “current_object = nullptr”…then obj1 doesn’t become NULL but weird, it seems to point to garbage data. And then if I tried to create later again with “obj1 = new A()” I get destroy errors. It seems I can’t make a pointer point to null neither a new object it is not clean NULL’ed.

if I use:

  private:
   A* obj1; 
   B* obj2; 
   C* obj3; 
   Component* current_object;

I get leakage when closing the app. I think due to current_object pointer. Even writing in the destructor:

    current_object = nullpt

Finally else if I use:

   private:
   A* obj1; 
   B* obj2; 
   C* obj3
   ScopedPointer<Component>current_object;

It works for a while but it stops working after a few iterations…having all pointers pointing to one object…

So I din’t really understand the behaviour of ScopedPointers when serveral pointers point to the same object.

Any clarification from anybody ;D ??
I hope it helps to somebody else

BR


#2

I’m confused as to what you’re trying to accomplish here. Why do you need to construct a new object when a button is clicked? Why not construct it when the app is initialized, and make it active/visible when the button is clicked?

Also setting a pointer to nullptr doesn’t delete the underling object. You need to explicitly call delete to call that object’s destructor and deallocate the memory.

If your issue is that you do not know how many objects are going to be constructed at compile time, you can use OwnedArray to hold onto the pointers.


#3

Hi Holy_City, thanks for your response,

The thing is that I would like to have one panel living at a time in order to save resources (I guess ;D). AS the Juce Demo does at MainWindow using “currentdemo” to hold a demo. The drawback I see with this is that “currentdemo” only can access to generic component methods. So If we wanted to change anyparameter of a demo from MainWindow, I don’t know how I would do it.

I thought about OwnedArray, but all object should inherit from the same class in order to access to their specific methods,


#4

To solve your direct problem, you will be fine, if you just swap the A, B and C pointers to ScopedPointers and use a raw pointer as current_object:

private:
ScopedPointer<A> obj1; 
ScopedPointer<B> obj2; 
ScopedPointer<C> obj3
Component::SafePointer<Component> current_object;

That way the life cycle of all objects is guaranteed. And the current_object just points to it. Using the safePointer to the component ensures, that the current_object is set to nullptr, in case the pointee is deleted.

But I would suggest to do a little basic tutorial about OO principles and polymorphism. With that knowledge you will achieve way nicer architectures. Another keyword for further research is dynamic_cast, which can help you to figure, if your component is of a specific derived class.

HTH