Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > Problem: how to use one std container to store multiple types?

Reply
Thread Tools

Problem: how to use one std container to store multiple types?

 
 
Manuel
Guest
Posts: n/a
 
      12-27-2005
Hi.
Before all, please excuse me for bad english and for very newbie
questions. I hope to don't boring you.

I'm trying to write a very simple GUI using openGL.
So I'm writing some different widgets classes, like buttons, images,
slider, etc...

Each class has a draw() method.

The idea is to put all widget to draw in a vector, and after, in pseudocode:

-----------------------------
for each widget w in vector:
w.draw()
-----------------------------

So I should declare the vector, like

vector<widget> widgetList;

and this is my trouble: I've different classes (that has some common
methods, like draw(), on(), off() etc...) and I should put all in one
std container. It's possible?


Really I don't know even how to declare the vector. In example, if I've
the class

----------------------------
class foo {
private:
int width;
int height;
public:
int getWidth();
int getHeight();
};
----------------------------

how to declare a container for foo? Surely not writing

vector<foo> fooList;

Should I use typedef? Can you explain me this?

I know I'm a newbie and maybe these are very silly questions. However I
can't find these info on the books I'm reading (they are for beginners,
and don't write about STD) and the same using google.
Can you help me?

Thanks,


Manuel



 
Reply With Quote
 
 
 
 
=?UTF-8?B?TWF0ZXVzeiDFgW9za290?=
Guest
Posts: n/a
 
      12-27-2005
Manuel wrote:
>
> I'm trying to write a very simple GUI using openGL. So I'm writing
> some different widgets classes, like buttons, images, slider, etc...
>
> Each class has a draw() method.
>
> The idea is to put all widget to draw in a vector, and after, in
> pseudocode:
>
> ----------------------------- for each widget w in vector: w.draw()
> -----------------------------
>


Look at Design Pattern called Composite which can be used to wrap such
structure easily. GoF's book [1] includes case study very similar to
your problem so you may find this book intersting.

Simply, create abstract base class i.e. Widget and
inherit concrete (specialized) gadgets from the Widget.
Declare in Widget pure virtual method i.e. void draw(canvas)
and implement it in every concrete widget suitably.
Finally, store all widgets in a container through pointer to the base
class Widget (dynamic polymorphism).


> So I should declare the vector, like
>
> vector<widget> widgetList;
>
> and this is my trouble: I've different classes (that has some common
> methods, like draw(), on(), off() etc...) and I should put all in
> one std container. It's possible?
>


Yes, do it as I explained above.
Here is simple implementation which should help to understand that idea:

#include <algorithm>
#include <iostream>
#include <vector>
////////////////////////////////////////////////////////////
struct DeleteObject
{
template <typename T>
void operator()(const T* ptr) const
{
delete ptr;
}
};
////////////////////////////////////////////////////////////
class Widget
{
public:
virtual void draw() const = 0;
virtual ~Widget() {}
};
class Button : public Widget
{
public:
void draw() const { std::cout << "Drawing Button" << std::endl; }
};
class Label : public Widget
{
public:
void draw() const { std::cout << "Drawing Label" << std::endl; }
};
class Slider : public Widget
{
public:
void draw() const { std::cout << "Drawing Slider" << std::endl; }
};

int main()
{
std::vector<Widget*> v;
v.push_back(new Button());
v.push_back(new Label());
v.push_back(new Slider());
v.push_back(new Button());

std::vector<Widget*>::const_iterator it;
for (it = v.begin(); it != v.end(); ++it)
{
(*it)->draw();
}

// Delete widgets
std::for_each(v.begin(), v.end(), DeleteObject());

return 0;
}
////////////////////////////////////////////////////////////

[1] Design Patterns: Elements of Reusable Object-Oriented Software
by Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides

Cheers
--
Mateusz Łoskot
http://mateusz.loskot.net
 
Reply With Quote
 
 
 
 
Manuel
Guest
Posts: n/a
 
      12-27-2005
Mateusz Łoskot wrote:

> Look at Design Pattern called Composite which can be used to wrap such
> structure easily. GoF's book [1] includes case study very similar to
> your problem so you may find this book intersting.
>
> Simply, create abstract base class i.e. Widget and
> inherit concrete (specialized) gadgets from the Widget.
> Declare in Widget pure virtual method i.e. void draw(canvas)
> and implement it in every concrete widget suitably.
> Finally, store all widgets in a container through pointer to the base
> class Widget (dynamic polymorphism).


Thanks you very much for the example!!

Some questions:

1) What happen if I use v.clear() instead DeleteObject() ??
2) In your example each class has the same number of methods. But what
happen if some classes have different numbers of methods? Should be not
a problem, right ??
3) Exist other way instead using a pointer in std::vector<Widget*> v; ??

Again, thanks, THANKS!

Ciao,

Manuel
 
Reply With Quote
 
=?UTF-8?B?TWF0ZXVzeiDFgW9za290?=
Guest
Posts: n/a
 
      12-27-2005
Manuel wrote:
>
> Thanks you very much for the example!!
>


You're welcome!

> Some questions:
>
> 1) What happen if I use v.clear() instead DeleteObject() ??


Look at older thread titled "STL map and memory management (clear() )",
about Dec, 15.

> 2) In your example each class has the same number of methods. But
> what happen if some classes have different numbers of methods? Should
> be not a problem, right ??


No problem. But remember that only common members may be accessed during
iterations (without casting). I mean, when iterating you "can see" all
widgets "through" base class interface - Widget.
Just a figurative explanation

> 3) Exist other way instead using a pointer in std::vector<Widget*> v;
> ??
>


In your particular solution I don't see anything better - abstract base
class allow you to access specialized types through unified interface
(declared in base class). I strongly recommend you to read GoF's
explanation of Composite, then may be you will get the idea behind it
more clear.

Note: you can use "smart pointers" instead of raw pointers. Then memory
management is much simplier. Here they are:
http://www.boost.org/libs/smart_ptr/smart_ptr.htm

Cheers
--
Mateusz Łoskot
http://mateusz.loskot.net
 
Reply With Quote
 
Manuel
Guest
Posts: n/a
 
      12-27-2005
Mateusz Łoskot wrote:

> You're welcome!

[...]
> Look at older thread titled "STL map and memory management (clear() )",
> about Dec, 15.

[...]
>I strongly recommend you to read GoF's
> explanation of Composite, then may be you will get the idea behind it
> more clear.
>
> Note: you can use "smart pointers" instead of raw pointers. Then memory
> management is much simplier. Here they are:
> http://www.boost.org/libs/smart_ptr/smart_ptr.htm



THANKS!!
I'll study your suggestions and trying some experiments before boring
you with other newbie questions.

Best Regards,

Manuel
 
Reply With Quote
 
BobR
Guest
Posts: n/a
 
      12-27-2005

Manuel wrote in message <43b091a3$0$1078$(E-Mail Removed)>.. .
>>Mateusz Łoskot wrote:


>Some questions:
>
>1) What happen if I use v.clear() instead DeleteObject() ??


You would leave objects in memory with no way to delete them. If you want to
use 'v.clear()', you can do it this way:

int main(){
std::vector<Widget*> v;
Button Btn;
v.push_back( &Btn );
Label Lbl;
v.push_back( &Lbl );
// .... etc. ....
std::vector<Widget*>::const_iterator it;
for (it = v.begin(); it != v.end(); ++it){
(*it)->draw();
}

v.clear() // vector will empty at this point.
Label Lbl2;
v.push_back( &Lbl2 );
v.clear() // vector will empty at this point.
return 0;
} // Btn, Lbl, etc. destructors will be invoked at this point.

Also read what Mateusz suggested.

Bruce Eckel, in his book 'Thinking in C++' vol 2, has another way to handle
the pattern (which he calls the 'Command pattern' ). You can download a legal
copy of the book here: http://www.bruceeckel.com/ [ref: //:
C10:CommandPattern.cpp ]

--
Bob R
POVrookie


 
Reply With Quote
 
Manuel
Guest
Posts: n/a
 
      12-27-2005
BobR wrote:

> Bruce Eckel, in his book 'Thinking in C++' vol 2, has another way to handle
> the pattern (which he calls the 'Command pattern' ). You can download a legal
> copy of the book here: http://www.bruceeckel.com/ [ref: //:
> C10:CommandPattern.cpp ]



Thanks...a lot of things to read


> POVrookie


Curiosity: Are you POVray user?

Ciao,

Manuel
 
Reply With Quote
 
Axter
Guest
Posts: n/a
 
      12-27-2005

Manuel wrote:
> Mateusz Loskot wrote:
>
> > You're welcome!

> [...]
> > Look at older thread titled "STL map and memory management (clear() )",
> > about Dec, 15.

> [...]
> >I strongly recommend you to read GoF's
> > explanation of Composite, then may be you will get the idea behind it
> > more clear.
> >
> > Note: you can use "smart pointers" instead of raw pointers. Then memory
> > management is much simplier. Here they are:
> > http://www.boost.org/libs/smart_ptr/smart_ptr.htm

>
>
> THANKS!!
> I'll study your suggestions and trying some experiments before boring
> you with other newbie questions.


I recommend you use a deep copy (clone) smart pointer, instead.
http://code.axter.com/copy_ptr.h
or a COW smart pointer
http://code.axter.com/cow_ptr.h

Both the copy_ptr and the cow_ptr can perform a deep copy when needed.
Example usage:
vector<copy_ptr<foo> > vFoo;
vFoo.push_back(new FooDerived);

You can use the boost::shared_ptr only if you're sure sharing the
pointee will not negatively effect your code. In most cases, this is
rarely what you want in a container.

Boost also has a set of pointer containers, but the interface is poor,
and does not match the STL containers very well.
I recommend using copy_ptr or cow_pt instead.

For more information, read the following related Article:
http://www.codeguru.com/cpp/cpp/algo...le.php/c10407/

In the above article it uses a clone_ptr smart pointer, but the
copy_ptr is a more optimize and complete version of the clone_ptr class.

 
Reply With Quote
 
BobR
Guest
Posts: n/a
 
      12-27-2005

Manuel wrote in message <43b1097b$0$1071$(E-Mail Removed)>.. .
>BobR wrote:
>> Bruce Eckel, in his book 'Thinking in C++' vol 2, has another way to

handle
>> the pattern (which he calls the 'Command pattern' ). You can download a

legal
>> copy of the book here: http://www.bruceeckel.com/ [ref: //:
>> C10:CommandPattern.cpp ]

>
>Thanks...a lot of things to read
>
>
>> POVrookie

>
>Curiosity: Are you POVray user?


Yes. I am still a POVray rookie because I have been spending more time
learning C++.
One of my current projects is for POVray (though it also outputs OGL, RAW,
RAD, OBJ, TIN, RIB). It makes a 3D Rock (as triangle mesh) and
displays/animates in a OpenGL window in wxWidgets.

Some people think that POV is Point-Of-View, and I just answer them with a
smiley-face :-}

--
Bob R
POVrookie
--
POVray: http://www.povray.org/


 
Reply With Quote
 
Manuel
Guest
Posts: n/a
 
      12-28-2005
Can you explain me (please be patient) because this structure

struct DeleteObject
{
template <typename T>
void operator()(const T* ptr) const
{
delete ptr;
}
};

instead a function like

DeleteObject( *ptr){ delete ptr; };

??

Thanks,

Manuel
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Re: How include a large array? Edward A. Falk C Programming 1 04-04-2013 08:07 PM
Which container - std::pair or std::map ? Bart Simpson C++ 6 03-13-2006 01:09 PM
/usr/bin/ld: ../../dist/lib/libjsdombase_s.a(BlockGrouper.o)(.text+0x98): unresolvable relocation against symbol `std::basic_ostream<char, std::char_traits<char> >& std::endl<char, std::char_traits<char> >(std::basic_ostre silverburgh.meryl@gmail.com C++ 3 03-09-2006 12:14 AM
std::transform container => std::abs(container) Steven T. Hatton C++ 4 12-05-2004 07:10 AM
std::container::iterator vs std::container::pointer Vivi Orunitia C++ 11 02-04-2004 08:09 AM



Advertisments