Re: noob question - destructors - freeing memory... POSSIBLE SOLUTION
FOUND?
On 01/02/2012 08:47 PM, LR wrote:
someone wrote:
On 01/02/2012 03:11 AM, LR wrote:
someone wrote:
On 01/01/2012 10:03 AM, Juha Nieminen wrote:
someone<newsboost@gmail.com> wrote:
I think std::vector is a little easier to deal with.
Maybe... I'm just a little bit stupid and afraid. So...
Try it.
Done it!
(now I only need to somehow detect that std::vector destructors are also
being called when exit() happens, just so I can sleep better at night) -
I just wrote about this concern in another reply...
--- main.cpp ---
drawableObj allObjs; // must be global!
int main(int argc, char** argv)
{
drawableObj *testGearPtr =
new gearClass( .... ); // rotSpeed etc, etc... bla.bla
drawableObj *testGearPtr2 =
new gearClass( .... ); // rotSpeed etc, etc... bla.bla
If you have a global allObjs, how do these pointers make their way into
that object?
Good question. They get pushed there ( into allObjs.pObjs to be precise
) from the constructors of derived class types, i.e:
class drawableObj
{
private:
public:
static vector<drawableObj*> pObjs;
..
}
With global scope, I declare this in top of main.cpp:
drawableObj allObjs; // must be global!
allObjs is of the base class type, i.e: drawableObj. I want to put all
graphical objects, with a reference into the base class. Here's my first
(currently also the only) derived graphical object type:
class gearClass : public drawableObj
{
// private
// public
gearClass::gearClass( ... ) // constructor
{
pObjs.push_back((gearClass*) this); // <---- HERE IS THE ANSWER
...
... etc
}
}
Isn't that an appropriate way of doing it?
Or is there better alternatives?
// ******* OpenGL starting... *******
glutInit(&argc, argv);
.... bla bla...
glutMainLoop(); // exits directly to OS from here...
return(0); // never comes here - just to satisfy compiler...
Odd, because it shouldn't be required at all.
Sure? Because main is supposed to return an integer, right?...
Not exactly sure, if I don't return anything, about if it'll complain
about missing int (I think so, but haven't tried it lately)...
class drawableObj
{
// private: // protected: // I don't have anything here
public:
// global+static pointer to all GRAPHICAL objs:
static vector<drawableObj*> pObjs;
Why is this static? Why not just make it a member class?
Exactly! I'm glad that you ask... Actually, since I put (with global
scope) - in top of main():
drawableObj allObjs;
Then I also thought that it didn't had to be static... I think I tried
to remove the static keyword (still public though)... But, the compiler
complains about it... Here's what I try:
1) removed the static word everywhere
2) then I get an error here :
--- file: helper.h ---
class drawableObj
{
public:
...
vector<drawableObj*> pObjs; // <--- LINE 47
...
};
--- file: helper.cpp ---
GLdouble findbox()
{
....
for (int z=0; z<(int) drawableObj::pObjs.size(); z++)
{
posX = ((gearClass*) drawableObj::pObjs[0])->posX; // 224
posY = ((gearClass*) drawableObj::pObjs[0])->posY; // 225
posZ = ((gearClass*) drawableObj::pObjs[0])->posZ; // 226
...
}
....
}
The 3 middle lines yield:
helper.cpp:224:37: error: from this location
helper.h:47:24: error: invalid use of non-static data member
?drawableObj::pObjs
helper.cpp:225:37: error: from this location
helper.h:47:24: error: invalid use of non-static data member
?drawableObj::pObjs
helper.cpp:226:37: error: from this location
helper.h:47:24: error: invalid use of non-static data member
?drawableObj::pObjs
What's it complaining about?
(FYI: findbox finds the smallest+biggest x,y and z-values, thus this
is used to set the screen limits)
drawableObj(); // constructor
// destructor
virtual ~drawableObj();
// member functions
virtual void draw(); //<---used in openGL display loop
void showNumObjs();
void test();
};
class gearClass : public drawableObj
Ok, now I'm confused. Is drawableObj some sort of polymorphic base
class, or is it a container for a whole bunch of objects.
Yes, isn't it both? I think it's a polymorphic base class (although I'm
not too experienced with this) !
And remember the global definition in top of main.cpp:
drawableObj allObjs;
{
private:
public:
bool memAllocated; // IMPORTANT TO KNOW IF DELETE HAS BEEN CALLED
Use std::vector and this problem doesn't arise.
Ok.
#include "gearClass.h" // for knowing "gearClass"-type
// NOT SURE ABOUT THIS, BUT COMPILER COMPLAINS IF NOT "EXTERN"...
extern vector<drawableObj*> drawableObj::pObjs;
Coupling your class with an external object made elsewhere probably
limits the utility of the class.
Hmmm. Not sure I understand exactly what I'm doing... Please elaborate -
I also don't understand fully how it "limits the utility of the class"
(because I'm not completely sure of what I'm doing)...
drawableObj::~drawableObj() // destructor
if ( ((gearClass*) drawableObj::pObjs[z])->memAllocated )
delete ((gearClass*) drawableObj::pObjs[z]);
Or use a shared pointer and avoid this.
But the idea is that I wanted polymorphism for all different kinds of
graphical objects. By shared pointer, do you mean a global pointer? I
don't like that idea... Here's why:
If I'm correct, then a shared pointer could only be used to point to all
(gearClass*) drawableObj (gearClass is a derived class, from
drawableObj). But I want the program to be able to handle more than one
class. Currently I only have gearClass deriving from drawableObj.
Suppose later I add extra classes like: cylinder, sphere, box, all 3
deriving from base class "drawableObj". Then I would like one single
"interface" to all those member functions that e.g. updates the display
- btw I found an error in my code. Now I update my display in a very
clean way, I think:
void display()
{
....
for (int z=0; z<(int) drawableObj::pObjs.size(); z++)
{
glPushMatrix();
(drawableObj::pObjs[z])->updateDisplay(); // could be any kind
glPopMatrix();
}
....
}
--- gearClass.cpp ---
gearClass::gearClass() // constructor
{
drawableObj::pObjs.push_back((gearClass*) this); // ISN'T THIS NICE ??
... bla bla...
No. I don't think so. Using a global like this seems like a bad idea.
I think it's better to decouple things.
Can you elaborate on why you think it's not nice?
Isn't my updating of the screen (in display(), see right above) nice ?
======== that was possible solution, please give some input ========
Final remarks:
I snipped a lot and just hit a few points. I think what you're doing is
asking for trouble.
FWIW, here's my suggestion. Most of it is just trace so you can see
what's going on. I consider this to be a snippet. For example, it would
be a better idea to put the classes and implementations in header and
source files.
Ok - thank you. But first I want to compile it - then I can move it into
separate files... What compiler are you using? I get quite some errors with:
g++ (Ubuntu/Linaro 4.6.1-9ubuntu3) 4.6.1
You might want to try creating a new project, copying the code, and
seeing what happens.
Thank you... There are some new things to learn, I can see that... It
doesn't compile, so I'll just write what my compiler says:
-----------------------
#include<iostream>
#include<string>
#include<vector>
#include<memory>
class DrawObjectBase {
public:
DrawObjectBase() {
std::cout<< "DrawObjectBase("<< this<< ")"<< std::endl;
}
virtual ~DrawObjectBase() {
std::cout<< "~DrawObjectBase("<< this<< ")"<< std::endl;
}
virtual void draw(const std::string&someParameter) const {
std::cout
<< "DrawObjectBase::draw("
<< this
<< ","
<< someParameter
<< ")"
<< std::endl;
}
};
class Star : public DrawObjectBase {
public:
Star()
:
DrawObjectBase()
{
std::cout<< "Star("<< this<< ")"<< std::endl;
}
~Star() {
std::cout<< "~Star("<< this<< ")"<< std::endl;
}
void draw(const std::string&s) const {
std::cout<< "Star::draw("<< this<< ","<< s<< ")"<< std::endl;
}
};
class Planet : public DrawObjectBase {
public:
Planet()
:
DrawObjectBase()
{
std::cout<< "Planet("<< this<< ")"<< std::endl;
}
~Planet() {
std::cout<< "~Planet("<< this<< ")"<< std::endl;
}
void draw(const std::string&s) const {
std::cout
<< "Planet::draw("<< this<< ","<< s<< ")"<< std::endl;
}
};
class DrawObjects {
// this isn't the best way to do this,
// just an example.
// a point of departure, not a destination.
public:
// maybe these typedefs should be classes on their own
typedef
std::tr1::shared_ptr<DrawObjectBase> DrawObjectBaseContainer;
test.cpp:66:9: error: ?tr1? in namespace ?std? does not name a type
typedef std::vector<DrawObjectBaseContainer> DrawObjectsContainer;
test.cpp:67:25: error: ?DrawObjectBaseContainer? was not declared in
this scope
test.cpp:67:48: error: template argument 1 is invalid
test.cpp:67:48: error: template argument 2 is invalid
DrawObjectsContainer objects; // public isn't great here...
public:
DrawObjects() : objects() {} // or howver many you need.
void add(const DrawObjectBaseContainer&d) {
test.cpp:71:20: error: ?DrawObjectBaseContainer? does not name a type
test.cpp:71:45: error: ISO C++ forbids declaration of ?d? with no type
[-fpermissive]
objects.push_back(DrawObjectBaseContainer(d));
test.cpp: In member function ?void DrawObjects::add(const int&)?:
test.cpp:72:17: error: request for member ?push_back? in
?((DrawObjects*)this)->DrawObjects::objects?, which is of non-class type
?DrawObjects::DrawObjectsContainer {aka int}?
test.cpp:72:52: error: ?DrawObjectBaseContainer? was not declared in
this scope
test.cpp: In member function ?void DrawObjects::draw(const string&) const?:
}
void draw(const std::string&someParameter) const {
for(DrawObjectsContainer::const_iterator
i=objects.begin();
test.cpp:75:35: error: invalid use of qualified-name ?::const_iterator?
test.cpp:75:50: error: expected ?;? before ?i?
test.cpp:75:50: error: ?i? was not declared in this scope
test.cpp:75:60: error: request for member ?begin? in ?((const
DrawObjects*)this)->DrawObjects::objects?, which is of non-class type
?const DrawObjectsContainer {aka const int}?
i!=objects.end();
test.cpp:76:28: error: request for member ?end? in ?((const
DrawObjects*)this)->DrawObjects::objects?, which is of non-class type
?const DrawObjectsContainer {aka const int}?
test.cpp:76:33: error: expected ?)? before ?;? token
i++) {
test.cpp:77:21: error: ?i? was not declared in this scope
test.cpp:77:24: error: expected ?;? before ?)? token
i->get()->draw(someParameter);
}
}
};
DrawObjects ourGlobalObjects;
void f() {
ourGlobalObjects
.add(DrawObjects::DrawObjectBaseContainer(new Star()));
test.cpp:88:14: error: ?DrawObjectBaseContainer? is not a member of
?DrawObjects?
ourGlobalObjects
.add(DrawObjects::DrawObjectBaseContainer(new Planet()));
test.cpp:90:14: error: ?DrawObjectBaseContainer? is not a member of
?DrawObjects?
ourGlobalObjects
.add(DrawObjects::DrawObjectBaseContainer(new Planet()));
test.cpp:92:14: error: ?DrawObjectBaseContainer? is not a member of
?DrawObjects?
ourGlobalObjects.draw("Draw Once");
ourGlobalObjects.draw("Draw Again");
}
int main() {
f();
exit(0); // because....
}
hmmmm.... Do I need to enable some compiler switch? You using MS visual
studio? I guess you're not using G++ with all these errors I get, are you?
-------------------------------------------
And the output is,
DrawObjectBase(00345768)
Star(00345768)
DrawObjectBase(003468B8)
Planet(003468B8)
DrawObjectBase(00346880)
Planet(00346880)
Star::draw(00345768,Draw Once)
Planet::draw(003468B8,Draw Once)
Planet::draw(00346880,Draw Once)
Star::draw(00345768,Draw Again)
Planet::draw(003468B8,Draw Again)
Planet::draw(00346880,Draw Again)
~Star(00345768)
~DrawObjectBase(00345768)
~Planet(003468B8)
~DrawObjectBase(003468B8)
~Planet(00346880)
~DrawObjectBase(00346880)
----------------------------------
Sounds very nice too... Unfortunately, the example doesn't compile
here... I'll try to take a closer look tomorrow evening, I guess...
Thank you...