An Array in an Array & type clarification


#1

Hi All!

At the risk of being shot down I ask this question :slight_smile:

I am trying to make a dynamic program that arrange objects according to the presets in a specific class, only created for that purpose. I, however, wish to make the function able to take different types of objects (in this case Button & Hyperlink & Label) and arrange them according to their types. I have therefore created an Array which takes Component -objects and are passing these to the function doing the arrangement of objects. In this way I am sure to achieve a consistent layout no matter the types or amount of objects I send to the function.

SO

I have 3 questions.

  1. Is it legal to do this type of “generic” passing of Component-child objects to an Array taking Component objects? (like Button & Hyperlink & Label which all inherent from the Component class)
  2. Is it legal to put an Array<Component> inside of another Array ? like so: Array<Array<Component>> I would like to be able to pass an Array of Array<Component>-objects to enable my function to arrange chunks of objects. Like 3 blocks of objects: 1 block with 3 objects, 1 block with 5 objects, 1 block with 2 objects… you get the idea.
  3. If all of this IS legal, and I just don’t have the overview to comprehend my own code just yet -How then, do you access the types of the objects in the Array<Component> ? I have tried looping through the Array using the typeid(singleBlockArray[i]).name()-method, but they all print out class juce::Component.

As you may have guessed I have had some success doing this Array<Array<Component>>-kinda’ thing, but I very often get these weird errors which points to places in the Juce_Array-files, which gets me thinking that this practice might be wrong all together.

Some code for clarification:

// ArrangingClass.h:

class ArrangingClass
{
	public:
		ArrangingClass(Array<Array<Component>> multipleBlocksArray);
};

//ArrangingClass.cpp:

ArrangingClass::ArrangingClass(Array<Array<Component>> multipleBlocksArray)
{
	for (int i = 0; i < multipleBlocksArray.size(); i++)
	{
		DBG("This is object-block number: " + i); // For printing in Visual Studio			
		Array<Component> singleBlockArray = multipleBlocksArray[i];
		for (int i = 0; i < singleBlockArray.size(); i++)
		{
			DBG("This object is of type: " + typeid(singleBlockArray[i]).name()); // For printing in Visual Studio
				
			// Do some arranging magic
		}
	}
}

Any help is appreciated :slight_smile:


#2

You need to use Component* instead of Component as the array element. Or rather ScopedPointer< Component > or similar in order to not leak memory. Also instead of typeid() you might find dynamic_cast more useful.


#3

Sure, that’s the whole point of polymorphism

Yes, that’s also possible. See @xenakios answer, he was faster :wink:

One option is dynamic_cast, or the more OO-version would be, to create an interface that all your three components conform to. So the Array will hold objects of type of your interface:

class MyGuiInterface {
public:
    void foo() = 0;
}

class MySlider : public Slider, public MyGuiInterface
{
public:
    void foo() {
        setValue (100); // as example
    }
}

class MyHyperlink : public HyperlinkButton, public MyGuiInterface
{
public:
    void foo() {
        setUrl ("http://juce.com"); // as example
    }
}

OwnedArray<OwnedArray<MyGuiInterface> > multipleBlocksArray;

Now all objects in multipleBlocksArray will understand the method foo(), and you don’t need to figure out which type they are.

again, here is dynamic_cast:

if (Button* button = dynamic_cast<Button*>(singleBlockArray[i])) {
    // use button
}

#4

Thanks @Xenakios & @daniel for your VERY rapid replies!

Glad to hear I weren’t completely off tracks. Visual Studios just keeps bugging me with strange errors that disappear when I clean the solution :confused: I have also changed my code to be Component*

The dynamic_cast looks like something I might enjoy, and thanks @daniel for the elaborate explanation :smile: Those sort of explicit examples are the best!


#5

I guess OwnedArray <Component> would be a better choice in that case