Sign in to follow this  
Part_E

When To Stop Encapsulating? - C++

Recommended Posts

Quick question for those more versed in C++ than I. I'm working on a custom GUI for my demo (Lots of element objects), and I had a question about encapsulation.

Say I have multiple button objects and I'm checking each on mouse move to see if any are highlighted (For picking / rollover purposes). Is it considered better practice to do the checking in the loop, or to have a method in the button object itself invoked for each button that does the checking? Here's my button object, set up currently to have each button check it's own bounding box - I've commented out the bit where it was checking in the loop by accessing the member variables of each button indirectly.

[code]
while( ThisButton ) {
//if((MouseX >= ThisButton->X && MouseX <= (ThisButton->X + ThisButton->Width)) && (MouseY >= ThisButton->Y && MouseY <= (ThisButton->Y + ThisButton->Height))) {
if( ThisButton->IsHighlighted( MouseX, MouseY ) ) {
OButton::HighlightedButton = ThisButton;
ThisButton = NULL;
break;
} else if( OButton::HighlightedButton == ThisButton ) {
OButton::HighlightedButton = NULL;
}

ThisButton = ThisButton->NextButton;
}
[/code]

And here's the method for checking if the button is highlighted:

[code]

bool OButton::IsHighlighted( int MouseX, int MouseY ) {
return((MouseX >= X && MouseX <= (X + Width)) && (MouseY >= Y && MouseY <= (Y + Height)));
}
[/code]

Actually, since HighlightedButton is a static member of OButton I could even set it inside the OButton::IsHighlighted() method

Share this post


Link to post
Share on other sites
I'd say check as you are, with a method, for the simple reason that you could have the check a virtual method, then later if you want to add a circular button, whose check logic is different, the remainder of the code isn't affected.

This ThisButton->NextButton stuff is a bit concerning though. Why aren't you storing your GUI elements in a standard container?

Share this post


Link to post
Share on other sites
[quote name='Aardvajk' timestamp='1307200598' post='4819431']
I'd say check as you are, with a method, for the simple reason that you could have the check a virtual method, then later if you want to add a circular button, whose check logic is different, the remainder of the code isn't affected.

This ThisButton->NextButton stuff is a bit concerning though. Why aren't you storing your GUI elements in a standard container?
[/quote]

Standard container? Like a GUI library or are you referring to C++ templates? If templates it's because no matter how many tutorials I read on them I still don't quite grasp the concept. Which is a shame because I do end up with quite a few objects with similar members. It's just that the only tutorials I ever find on templates are tutorials specifically about templates, which never offer examples of how you would actually use them. And all other (Game programming-specific) tutorials typically omit the use of templates. I'm guessing because explaining game programming concepts is difficult enough without also having to explain templates.

But I revised it a bit, since HighlightedButton is a static member of OButton I just stuck it's assignment in the IsHighlighted():

[code]

bool OButton::IsHighlighted( int MouseX, int MouseY ) {
if((MouseX >= X && MouseX <= (X + Width)) && (MouseY >= Y && MouseY <= (Y + Height))) {
HighlightedButton = this;
return true;
} else if( this == HighlightedButton ) {
HighlightedButton = NULL;
}
return false;
}
[/code]

And my loop is now just:

[code]

void CGUI::ProcessMouseMove( int MouseX, int MouseY, bool Left, bool Right ) {
if( !MenuList[CurrentMenu] )
return;

OButton *ThisButton = NULL;
ThisButton = MenuList[CurrentMenu]->FirstButton;

while( ( ThisButton ) && !ThisButton->IsHighlighted( MouseX, MouseY ) )
ThisButton = ThisButton->NextButton;
}[/code]

The ThisButton = ThisButton->NextButton is just bog standard linked list traversal.

Share this post


Link to post
Share on other sites
[quote name='Part_E' timestamp='1307201689' post='4819438']
The ThisButton = ThisButton->NextButton is just bog standard linked list traversal.
[/quote]

I wouldn't call it bog standard. C programmers used to do stuff like this, but it is a pointless design choice in C++. It is never a good idea to mix up the implementation of an object with details of how lists of such object are stored, if for no other reason than it becomes impossible to take advantage of the standard libraries algorithms that generalise operations on lists of objects.

You don't need to understand templates to [i]use[/i] the standard containers. You are already using std::string, which is just a typedef of a template and essentially a container of characters. Start with std::vector and never look back.

[source lang="c++"]
class GUIElement
{
public:
virtual ~GUIElement(){ }

virtual bool IsHighlighted()=0;
};

class Button : public GUIElement
{
virtual bool IsHighlighted(){ /* ... */ }
};

std::vector<GUIElement*> elements;

void f()
{
elements.push_back(new Button());
elements.push_back(new Button());

// for simplicity, ignoring iterators for now

for(int i=0;i<elements.size();++i)
{
if(elements[i]->IsHighlighted()) HighlightedElement=elements[i];
}

for(int i=0;i<elements.size();++i) delete elements[i];
}
[/source]

It is as simple as suffixing the container type with the class you want in angle brackets. Then std::vector just works the same as a native array really.

There are more appropriate solutions for storing containers of pointers but since you are new to the standard library, I'll ignore that for now.

Share this post


Link to post
Share on other sites
[quote name='Aardvajk' timestamp='1307202602' post='4819442']
[quote name='Part_E' timestamp='1307201689' post='4819438']
The ThisButton = ThisButton->NextButton is just bog standard linked list traversal.
[/quote]

I wouldn't call it bog standard. C programmers used to do stuff like this, but it is a pointless design choice in C++. It is never a good idea to mix up the implementation of an object with details of how lists of such object are stored, if for no other reason than it becomes impossible to take advantage of the standard libraries algorithms that generalise operations on lists of objects.

You don't need to understand templates to [i]use[/i] the standard containers. You are already using std::string, which is just a typedef of a template and essentially a container of characters. Start with std::vector and never look back.

[source lang="c++"]
class GUIElement
{
public:
virtual ~GUIElement(){ }

virtual bool IsHighlighted()=0;
};

class Button : public GUIElement
{
virtual bool IsHighlighted(){ /* ... */ }
};

std::vector<GUIElement*> elements;

void f()
{
elements.push_back(new Button());
elements.push_back(new Button());

// for simplicity, ignoring iterators for now

for(int i=0;i<elements.size();++i)
{
if(elements[i]->IsHighlighted()) HighlightedElement=elements[i];
}

for(int i=0;i<elements.size();++i) delete elements[i];
}
[/source]

It is as simple as suffixing the container type with the class you want in angle brackets. Then std::vector just works the same as a native array really.

There are more appropriate solutions for storing containers of pointers but since you are new to the standard library, I'll ignore that for now.
[/quote]


lol - For the longest time I assumed <Vector>s were templates that stored an x, y, z coordinate and an angle. Y'know... Like a vector. Never realized they were actually containers for linked objects. That's much simpler than the custom methods I was writing to push and pop objects into linked lists and trees.

Crud - Now this means I have to completely repurpose my octree code to use vectors =(
Can I make vectors of vectors of vectors? Hmmm...

Thanks though, Aardvajk.

Share this post


Link to post
Share on other sites
Actually, std::vector is more similar to a native array than a linked list. std::list implements a linked list for you. std::vector stores all objects in contiguous memory and will copy and destroy its contents when it resizes, so beware.

The name vector seems confusing, but is mathematically correct technically - a homogenous, single dimensional tensor. I believe there was discussion at the time about naming it std::array but this was dropped for some reason.

Yes, you can make a vector of vectors, or a vector of vectors of vectors:

[source lang="c++"]
std::vector<std::vector<int> > ints;

typdedef std::vector<std::vector<int> > ints_vector;

std::vector<ints_vector> getting_silly_now;
[/source]

But a vector of vectors is essentially a ragged array of lists of seperate chunks of memory. If you want a rectangular array, similar to a native 2D array, you are better to use a single vector of size width*height and access via [(y*width)+x] sort of thing.

Again, there are better solutions but don't want to run too far ahead.

Share this post


Link to post
Share on other sites
[quote name='Aardvajk' timestamp='1307204418' post='4819450']
Actually, std::vector is more similar to a native array than a linked list. std::list implements a linked list for you. std::vector stores all objects in contiguous memory and will copy and destroy its contents when it resizes, so beware.

Yes, you can make a vector of vectors, or a vector of vectors of vectors:

[source lang="c++"]
std::vector<std::vector<int> > ints;

typdedef std::vector<std::vector<int> > ints_vector;

std::vector<ints_vector> getting_silly_now;
[/source]

But a vector of vectors is essentially a ragged array of lists of seperate chunks of memory. If you want a rectangular array, similar to a native 2D array, you are better to use a single vector of size width*height and access via [(y*width)+x] sort of thing.

Again, there are better solutions but don't want to run too far ahead.
[/quote]

Ok, well for most GUI elements I'll just be loading, indexing, and unloading as statically sized lists, so vector will probably be ok. No 'push to top', 'pop from middle', etc necessary. But that's good to keep in mind for the stuff that won't be so static. And please, be as technical as you freakin' want. I'm sick of tutorials pussy-footing around methods that're considered 'too complicated' even though they're the methods people actually, y'know, use.

Share this post


Link to post
Share on other sites
[quote name='Part_E' timestamp='1307203966' post='4819447']
[quote name='Aardvajk' timestamp='1307202602' post='4819442']
[quote name='Part_E' timestamp='1307201689' post='4819438']
The ThisButton = ThisButton->NextButton is just bog standard linked list traversal.
[/quote]

I wouldn't call it bog standard. C programmers used to do stuff like this, but it is a pointless design choice in C++. It is never a good idea to mix up the implementation of an object with details of how lists of such object are stored, if for no other reason than it becomes impossible to take advantage of the standard libraries algorithms that generalise operations on lists of objects.

You don't need to understand templates to [i]use[/i] the standard containers. You are already using std::string, which is just a typedef of a template and essentially a container of characters. Start with std::vector and never look back.

[source lang="c++"]
class GUIElement
{
public:
virtual ~GUIElement(){ }

virtual bool IsHighlighted()=0;
};

class Button : public GUIElement
{
virtual bool IsHighlighted(){ /* ... */ }
};

std::vector<GUIElement*> elements;

void f()
{
elements.push_back(new Button());
elements.push_back(new Button());

// for simplicity, ignoring iterators for now

for(int i=0;i<elements.size();++i)
{
if(elements[i]->IsHighlighted()) HighlightedElement=elements[i];
}

for(int i=0;i<elements.size();++i) delete elements[i];
}
[/source]

It is as simple as suffixing the container type with the class you want in angle brackets. Then std::vector just works the same as a native array really.

There are more appropriate solutions for storing containers of pointers but since you are new to the standard library, I'll ignore that for now.
[/quote]


lol - For the longest time I assumed <Vector>s were templates that stored an x, y, z coordinate and an angle. Y'know... Like a vector. Never realized they were actually containers for linked objects. That's much simpler than the custom methods I was writing to push and pop objects into linked lists and trees.

Crud - Now this means I have to completely repurpose my octree code to use vectors =(
Can I make vectors of vectors of vectors? Hmmm...

Thanks though, Aardvajk.


[/quote]

Yes, you can make vector's of vectors. If I could give you one piece of advice it's stop everything you are doing and read up on c++ standard library datatypes. Until you do, I guarantee you will be creating "bad" code, essentially re-inventing the wheel over and over, while creating untold numbers of bugs implementing code that has been thoroughly vetted by the community.

At the very least, learn the major [url="http://www.cplusplus.com/reference/stl/"]STL Containers[/url], vector, deque, list and map at the very least. Once you know these it will change the very way you program.

I would also consider learning or at least being aware of [url="http://www.boost.org/doc/libs/1_46_1/"]Boost[/url] the official unofficial library of C++! :) Many common tasks have already been handled in Boost and again this code is well vetted, extremely well documented and damned handy. Something like [url="http://www.boost.org/doc/libs/1_46_1/doc/html/signals/tutorial.html#id2682409"]signals[/url] could completely change the fundamental design of your entire project. Of course [url="http://www.boost.org/doc/libs/1_46_1/libs/smart_ptr/smart_ptr.htm"]Smart Pointers[/url] are perhaps the most used BOOST template.

Share this post


Link to post
Share on other sites
Well, for storing a vector of pointers and for making multidimensional arrays I was going to suggest using boost::ptr_vector and boost::multi_array but if you are just starting out using the standard library, I'd get your head round that before delving into boost.

Don't mean to pussyfoot or suggest it is too complicated, just seems sensible to me to have a good idea of what the standard library can and can't do before opening the huge boost::can_of_worms. :)

Share this post


Link to post
Share on other sites
[quote name='Aardvajk' timestamp='1307204418' post='4819450']
But a vector of vectors is essentially a ragged array of lists of seperate chunks of memory. If you want a rectangular array, similar to a native 2D array, you are better to use a single vector of size width*height and access via [(y*width)+x] sort of thing.

Again, there are better solutions but don't want to run too far ahead.
[/quote]

I understand the suggestion you are making, but frankly this kinda hackish cludgery is so rife within the C world and should not be encouraged. A 2 dimensional datatype should BE a 2D datatype, even if behind the scenes it is implemented in the manner you are speaking. I would use a vector of vectors before I "faked it" using index math. Besides, your suggestion would not allow for a vector of a non-standard size. I would probably recommend boost multiarray here, if a vector of vectors just doesn't work for you.


EDIT: You commented while I was typing my reply ( stupid real world distractions! ;) ). In a nutshell, I agree with you completely in your follow up comment.

Share this post


Link to post
Share on other sites
[quote name='Aardvajk' timestamp='1307205688' post='4819463']
Well, for storing a vector of pointers and for making multidimensional arrays I was going to suggest using boost::ptr_vector and boost::multi_array but if you are just starting out using the standard library, I'd get your head round that before delving into boost.

Don't mean to pussyfoot or suggest it is too complicated, just seems sensible to me to have a good idea of what the standard library can and can't do before opening the huge boost::can_of_worms. :)
[/quote]

I would almost view boost as part of the standard C++ toolkit. I DO consider STL as part of C++. I frankly would recommend learning both upfront if at all possible. Wayyyyyyyy too many books, and frankly a lot of the open source code out there, use C++ as a better C and teach it accordingly. This I view as a mistake.

I read a very good article years ago on better ways of teach C++, I'll see if I can find it. ( I think it was Stroustrup himself ).

Share this post


Link to post
Share on other sites
Ok, I'm converting my custom lists to STL equivalents. But I had one more question pertaining to basic class organization.

I currently have this function here which processes basic mouse clicks:
[code]

void CGUI::ProcessMouseClick() {
if( !MenuList[CurrentMenu] )
return;

if( OButton::HighlightedButton )
return OnButtonAction( CurrentMenu, OButton::HighlightedButton->Action );
}
[/code]
Where both CurrentMenu and Action just hold enumerated ID numbers. OnButtonAction is pure virtual in CGUI and actually implemented in CGame where a big switch statement resides. Based on the ID of the current menu (Which is just what I'm calling a screenful of UI elements) and the button action. Actually, here:
[code]

void CGame::OnButtonAction( MenuType ThisMenu, ButtonAction ThisAction ) {
switch( ThisMenu ) {
case M_CHOOSE_RENDER:
switch( ThisAction ) {
case BA_TESTRENDER:
CurrentState = TEST_RENDER;
CGUI::OpenMenu( M_TEST );
break;
case BA_MAINRENDERER:
CurrentState = MAIN_RENDER;
CGUI::OpenMenu( M_HUD );
break;
}
break;
}
}
[/code]
Originally I had wanted the ButtonAction member of OButton to be a function pointer which points to a virtual function that's actually implemented in CGame. So I could do something like:

[code]

if( OButton::HighlightedButton )
OButton::HighlightedButton->*Action();
[/code]
But that was a nightmare that I never got working.
My question is, would the function pointer method have been a better option had I gotten it to work, or is my enumerated type solution viable enough?

Also, are vectors of pointers pre-initialized with NULL or do I need to explicitly do that with the iota function or something?

Share this post


Link to post
Share on other sites
[quote name='Serapth' timestamp='1307207104' post='4819471']
I would use a vector of vectors before I "faked it" using index math.
[/quote]

Well, my point was really just that a vector of vectors is a very different beast to a native 2D array - you end up effectively with a vector of pointers to separate chunks of memory for each row and there is no invariant preserved that the 2D array remains rectangular. There are also potential issues with cache coherency with the vector of vectors approach, although this is premature optimization of course.

I agree in principle that boost should be considered part of the standard library and treated as such, but in the real world, to a beginner who has said they have not learned about the standard library containers, my fear with diving in with the "Use boost::multiarray" type of comment is that it adds confusion, especially when the OP had stated problems understanding the existing standard templates.

But I certainly take on board your points.

Share this post


Link to post
Share on other sites
[quote name='Part_E' timestamp='1307213585' post='4819491']
But that was a nightmare that I never got working.
My question is, would the function pointer method have been a better option had I gotten it to work, or is my enumerated type solution viable enough?
[/quote]

This is a big topic, how to design this sort of thing. I'll pass on this and leave it to people with more expertise (plenty around here).

[quote name='Part_E' timestamp='1307213585' post='4819491']
Also, are vectors of pointers pre-initialized with NULL or do I need to explicitly do that with the iota function or something?
[/quote]

No, nothing is pre-initialized. But you shouldn't really need to. Just push_back the pointers as you create them. There is little point in pre-allocating a vector of pointers then assigning values by index. Just start with an empty vector, push_back the pointers as they are created and don't worry about how it all works under the hood.

Share this post


Link to post
Share on other sites
Why not have Action as a regular (non-virtual) member function. You can then have a ButtonAction delegate that can be linked:
[code]
class ButtonAction
{
public:
virtual ~ButtonAction()
{
}

virtual void onAction() = 0;
};

class Button
{
public:
// smart_ref: some imaginary non-null smart pointer like class
Button(smart_ref<ButtonAction> buttonAction)
:
buttonAction(buttonAction)
{
}

void click()
{
buttonAction->onAction();
}
private:
smart_ref<ButtonAction> buttonAction;
};

class ToggleTestRender : public ButtonAction
{
public:
ToggleTestRender(smart_ref<Game> game)
:
game(game)
{
}

virtual void onAction()
{
game->toggleTestRender();
}

private:
smart_ref<Game> game;
};

int main()
{
smart_ref<Game> game;
smart_ref<ToggleTestRender> toggleAction(game);

Button toggleButton(toggleAction);
toggleButton.click();
}
[/code]

Share this post


Link to post
Share on other sites
[quote name='Aardvajk' timestamp='1307222136' post='4819523']
[quote name='Serapth' timestamp='1307207104' post='4819471']
I would use a vector of vectors before I "faked it" using index math.
[/quote]

Well, my point was really just that a vector of vectors is a very different beast to a native 2D array - you end up effectively with a vector of pointers to separate chunks of memory for each row and there is no invariant preserved that the 2D array remains rectangular. There are also potential issues with cache coherency with the vector of vectors approach, although this is premature optimization of course.

I agree in principle that boost should be considered part of the standard library and treated as such, but in the real world, to a beginner who has said they have not learned about the standard library containers, my fear with diving in with the "Use boost::multiarray" type of comment is that it adds confusion, especially when the OP had stated problems understanding the existing standard templates.

But I certainly take on board your points.
[/quote]



I think the key is how it is taught. I would put forward that learning STL and BOOST as part of the language from the very beginning, would actually make the process EASIER. In a way, its the lack of standard libraries and memory management that hang up newbie ( and veteran! ) programmers. I think the key is, you teach people how to use BOOST ( and STL ), not HOW they work. Thats been my issue with so many C++ tutorials... they seem to insist on the underlying tech, as oppose to simply focus on functional use. Wrapping your head around using boost::multiarray is an order of magnitude easier than figuring out how the hell it was actually implemented!

This problem is by no means new, when I was in university, the language du jour was C and as we learned we would start with something like implementing a quicksort ( which lost lots of students ), instead of starting off using the built in qsort functionality and learning the details later. Teaching C++, just as with teaching just about anything, should start with as much instant gratification as possible, with the nitty gritty coming later. I mean when an auto mechanic is learning the trade, they don't generally start with a theoretical lesson on designing internal combustion engines, do they? This is basically how most C++ texts work.

Share this post


Link to post
Share on other sites
[quote name='rip-off' timestamp='1307223547' post='4819535']
Why not have Action as a regular (non-virtual) member function. You can then have a ButtonAction delegate that can be linked:
[code]
class ButtonAction
{
public:
virtual ~ButtonAction()
{
}

virtual void onAction() = 0;
};

class Button
{
public:
// smart_ref: some imaginary non-null smart pointer like class
Button(smart_ref<ButtonAction> buttonAction)
:
buttonAction(buttonAction)
{
}

void click()
{
buttonAction->onAction();
}
private:
smart_ref<ButtonAction> buttonAction;
};

class ToggleTestRender : public ButtonAction
{
public:
ToggleTestRender(smart_ref<Game> game)
:
game(game)
{
}

virtual void onAction()
{
game->toggleTestRender();
}

private:
smart_ref<Game> game;
};

int main()
{
smart_ref<Game> game;
smart_ref<ToggleTestRender> toggleAction(game);

Button toggleButton(toggleAction);
toggleButton.click();
}
[/code]
[/quote]


As to the original posters question, your way ( using a switch statement ) entirely depends on how many menus you are going to have. If you only have a menu or two, go for it. If you start adding more, that switch statement is going to get monstrously large and unmanageable.


I was thinking something along these lines as well. Although me usage of Java and C# these last years would incline to towards a pure virtual interface. In a post C world, function pointers should be mostly avoid, IMHO. The virtual keyword makes things so much cleaner, safer and easier, while effectively creating function pointers for you behind the scenes.

[code]
class IClickable {
public:
virtual void OnClick(ClickEvent) = 0;
virtual Rectangle GetClickRect() = 0;
};

class Button, public IClickable {
public:
virtual void OnClick(ClickEvent ce) {}
virtual Rectangle GetClickRect() { return _rect; }

private:
Rectange _rect;
};

[/code]

Then in your ClickManager you give the ability to register and unregister clickables, then it would be able to iterate through a clickable list, checking for a hit and on hit calling the OnClick() method.

The advantage to this is a) you can have clickables occupying the same space b) it scales better than the giant switch c) you aren't just confined to buttons, you can transparently add support for List Items, switches, etc... without a change to your ClickManager. Finally it should be abstracted enough that switching to a touch interface for example, would be trivial.

Share this post


Link to post
Share on other sites
[quote name='Serapth' timestamp='1307223860' post='4819537']
I think the key is how it is taught. I would put forward that learning STL and BOOST as part of the language from the very beginning, would actually make the process EASIER. In a way, its the lack of standard libraries and memory management that hang up newbie ( and veteran! ) programmers. I think the key is, you teach people how to use BOOST ( and STL ), not HOW they work. Thats been my issue with so many C++ tutorials... they seem to insist on the underlying tech, as oppose to simply focus on functional use. Wrapping your head around using boost::multiarray is an order of magnitude easier than figuring out how the hell it was actually implemented!

This problem is by no means new, when I was in university, the language du jour was C and as we learned we would start with something like implementing a quicksort ( which lost lots of students ), instead of starting off using the built in qsort functionality and learning the details later. Teaching C++, just as with teaching just about anything, should start with as much instant gratification as possible, with the nitty gritty coming later. I mean when an auto mechanic is learning the trade, they don't generally start with a theoretical lesson on designing internal combustion engines, do they? This is basically how most C++ texts work.
[/quote]

Totally agree with you, but don't want to hijack the thread. :)

Share this post


Link to post
Share on other sites
Alright, I've replaced all of my dynamic lists of objects with vectors of objects, at least in the GUI code so far, and everything seems OK - Perhaps even snappier ( I'm guessing because of the contiguous memory allocation ).

And I think I'll stick with the switch statement for now since deciding to separate some of the GUI elements from my list of 'menu' objects, such as the main game HUD, conversation windows, labels, etc. So once the main game loads it'll be using event methods that're different from OnButtonAction, which itself will only apply to a handful of 'menus' with a handful of buttons.

Thanks for explaining the STL though! I have a lot more reading to do, but it looks like boost also could really help with organizing my main game code. Entities and such.

I also implemented that GUI_Element wrapper class[size="2"] [color="#413544"]Aardvajk suggested. Although I did split the vector of it into an ActiveElements and a StaticElements vector, respectively. Since I don't really care to iterate through static things like text labels and images when picking.[/color][/size]

Share this post


Link to post
Share on other sites
Ah, also, little bump here as I have another question:

I've been reading in a few places that there are different implementations of the STL, specifically in regards to things like getting the sizeof a vector. Right now I'm using an ::iterator to loop through vectors, since that's the recommended method. But my main concern is that I'm trying to maintain cross-platform compatibility. Are there any other parts of the STL that may not be compatible across systems?

Share this post


Link to post
Share on other sites
Don't forget if you are pushing pointers you have new-ed into a std::vector<T*>, it is still your responsibility to delete those pointers, std::vector won't do that for you.

boost::ptr_vector is the container we alluded to earlier that will look after that for you, if you are interested in looking into boost. It also has the nice additional feature that you can do vec[3].hello() rather than vec[3]->hello() and the iterators will (I believe) act like you are working with concrete values rather than pointers as well.

Share this post


Link to post
Share on other sites
You shouldn't need to get the sizeof() a vector. It isn't a POD type, there are few (if any) reasonable things you could do with sizeof that make sense. You can use iterators or indices to loop through a vector. If you use indices it is more portable to use std::vector<T>::size_type rather than plain "int" - using "int" generates signed/unsigned warnings anyway.

[quote]
Are there any other parts of the STL that may not be compatible across systems?
[/quote]
In interface, they should be identical. That, we hope, is the point in having a standard library! They won't be binary compatible - even on a particular compiler with different compiler settings the binary layout of certain standard library types will be different.

At the moment we're seeing the crossover to C++0x, so some portions of the std namespace will not be available on all compilers, or you might need to access them using the std::tr1 namespace. But for most of the classes and functions you'll need to use they work across compilers.

Share this post


Link to post
Share on other sites
I have a feeling you may be looking at older pages. There used to be various versions of the STL created by various compiler teams or other companies. Early on, it was HP(creator), SGI, STLPort and Rogue Wave that were the norm and between each their were differences and nuiances. As time went on, the standard libraries became much much much more "standardized". I think it was C++98 when the standard became a bit more finalized.

Anyways, be careful about how old the documentation you are talking about is.

Share this post


Link to post
Share on other sites
Alright, sounds good then. More than likely I was looking at some old information. I've already pretty much scoured the internet for every STL example in existence by now it seems. And I should be OK on cleaning up considering I was creating, sorting and destroying dynamically allocated linked lists before vectors came along.

Will this do?

[code]

vector<OElement*>::iterator Iterator = ActiveElements.begin();

while( Iterator != ActiveElements.end() ) {
delete (*Iterator);
(*Iterator) = NULL; // <--- Is this actually necessary? I tend to er on the side of caution
Iterator++;
}
[/code]

Share this post


Link to post
Share on other sites
[quote name='Part_E' timestamp='1307234977' post='4819602']
(*Iterator) = NULL; // <--- Is this actually necessary? I tend to er on the side of caution
[/quote]

Not if you are not going to use the vector after you have done this. Nulling pointers is purely for when you need to test later whether they point to anything or not. Understand that the vector has no understanding that you are storing pointers in it and is not going to delete them for you.

You could write it more concisely:

[source lang="c++"]
for(vector<OElement*>::iterator Iterator=ActiveElements.begin();Iterator!=ActiveElements.end();++Iterator) delete *Iterator;
[/source]

If you are using a compiler that supports the new auto, even more concisely:

[source lang="c++"]
for(auto Iterator=ActiveElements.begin();Iterator!=ActiveElements.end();++Iterator) delete *Iterator;
[/source]

But it achieves the same thing as you have already written really. Main advantage of using the for loop is it doesn't add the Iterator variable to the enclosing scope.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this