S
someone
someone said:someone wrote:
On 01/01/2012 10:03 AM, Juha Nieminen wrote:
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...
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?
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)...
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:Objs.size(); z++)
{
posX = ((gearClass*) drawableObj:Objs[0])->posX; // 224
posY = ((gearClass*) drawableObj:Objs[0])->posY; // 225
posZ = ((gearClass*) drawableObj:Objs[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:Objs
helper.cpp:225:37: error: from this location
helper.h:47:24: error: invalid use of non-static data member
‘drawableObj:Objs
helper.cpp:226:37: error: from this location
helper.h:47:24: error: invalid use of non-static data member
‘drawableObj:Objs
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)
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;
Use std::vector and this problem doesn't arise.
Ok.
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() // destructorOr use a shared pointer and avoid this.if ( ((gearClass*) drawableObj:Objs[z])->memAllocated )
delete ((gearClass*) drawableObj:Objs[z]);
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:Objs.size(); z++)
{
glPushMatrix();
(drawableObj:Objs[z])->updateDisplay(); // could be any kind
glPopMatrix();
}
....
}
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 ?
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:bjects’, which is of non-class type
‘DrawObjects:rawObjectsContainer {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:bjects’, 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:bjects’, 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:rawObjectBaseContainer(new Star()));
test.cpp:88:14: error: ‘DrawObjectBaseContainer’ is not a member of
‘DrawObjects’
ourGlobalObjects
.add(DrawObjects:rawObjectBaseContainer(new Planet()));
test.cpp:90:14: error: ‘DrawObjectBaseContainer’ is not a member of
‘DrawObjects’
ourGlobalObjects
.add(DrawObjects:rawObjectBaseContainer(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...