Pointers & C++, Intermediate

Started by
8 comments, last by Enigma 18 years, 9 months ago
Is it possible to link from data source to each other using pointers, check example. class Face { vertices normal color texture // Reference to its parent Object *parent; }; class Object { numfaces Face *faces; // the actual faces } // Now in the example the structure looks simple but in my project most things are in lists or vectors so what happens is when a face is created the parent pointer should be set to the object so that when a face undergoes a transformation or a change and it requires more information then it can look to the parent. a good example of this is when extruding a face. the parent is required because n new faces are created to form the height or extrusion of the new face, Also other operations like subdivide and split Thanks
----------------------------

http://djoubert.co.uk
Advertisement
as far as i know of no... i just tryed it using two test classes and i got a type name expected error on Object *Parent line, which i had a feel would happen because i thought i had once tryed the same thing... its because you try to create a variable of a type that has not been defined yet unless you could define two classes at the same time...
When the world can't make you smile, program one that can
Yeah, it's possible. In order to get it to work, you need to use forward declarations for the classes, like this:

In Face.h:
class Object;class Face{/* pointers are all the same size, so the compiler doesn't need to know what Object really is, just that it's a class and you have a pointer to it. */  Object *parent; }

In Face.h:
#include <Face.h>#include <Object.h> // here is where you tell the compiler what Object isvoid Face::SomeFunction(){  parent->DoSomethingWithTheParent();}


You can then do the same process for Object. Just do "class Face;" before you define Object, and then include Face.h in Object.cpp, and you should be good to go.

However, one note, you can't do something like this:
class Object;class Face{  Object obj;}

Because the compiler needs to know the size of the Face class at compile time, it won't let you use an undefined class as a member. But using a pointer or reference to a class that's only been forward declared is fine.
Never tried, but put a

class Object;

before the declaration of Face so that Object is already known by the compiler before it gets to know Face. The full declaration of Object can stay right where it is.

Might work :-)

EDIT: Damn, a bit to late :-)
i just clicked post at which i posted quite some on why it can be done and that pointers only point to addresses. The real reason being is i dont have any formal c++ training only years experience in programming so some small stuff like this i miss out.

Would it be okay to do it this way

class CFace;
class CVertex;
class CObject;
////
class CVertex
{
cface *face
cobject *object
}
class CFace
{
cvertex *vert;
cobject *object
}
class CObject
{
cface *face;

}
----------------------------

http://djoubert.co.uk
i stand corrected thanks mmelson i didnt think or know of declaring the classes like that
When the world can't make you smile, program one that can
You *can* use forward declarations, but if possible try to avoid them because it usually indicates that something is wrong in your code (or rather, there is probably a better way).

to use the previous example....

class CFace;class CVertex;class CObject;////class CVertex{  cface *face  cobject *object};class CFace{  cvertex *vert;  cobject *object};class CObject{  cface *face;};


The problem is that each pointer will be 4bytes in size. This makes your vertex structure 20 bytes with pointers, 12 bytes without. Since there will be a lot of vertices, it would cost a fair amount of data. In this case, it may be better to consider storing indices rather than pointers since you might be able to get away with unsigned shorts (2bytes each, thus sizeof(cface) == 16). You could even use bitfields to store the indices, ie)

class CVertex{   struct {      unsigned short face_index:20;      unsigned short obj_index:12;   };};


This would still be 4 bytes for the 2 indices, however you'd now be able to index 1048576 vertices and 4096 objects rather than 65536 verts, 65536 objects.

If you start using indices, then obviously the vertices loose the ability to directly reference the faces or objects. To get around that, you probably want to transfer any functions that need to reference both the vertex and face into the object structure. That way the object is responsible for any direct references to IT'S OWN data (and can check things like if the pointer is valid).
Quote:Original post by RobTheBloke
You *can* use forward declarations, but if possible try to avoid them because it usually indicates that something is wrong in your code (or rather, there is probably a better way).

Nonsense, there are plenty of occasions where forward declarations are perfectly valid. For example a parent/child relationship where both classes need a pointer to each other.

Forward declarations are however a symptom of C++'s retarded single-pass compilation model.
Quote:Original post by OrangyTang
Quote:Original post by RobTheBloke
You *can* use forward declarations, but if possible try to avoid them because it usually indicates that something is wrong in your code (or rather, there is probably a better way).

Nonsense, there are plenty of occasions where forward declarations are perfectly valid. For example a parent/child relationship where both classes need a pointer to each other.

Forward declarations are however a symptom of C++'s retarded single-pass compilation model.


.... however, should the child be required by other classes independantly, you are forced to either check for a NULL parent or duplicate code (either via copy & paste, or the use of a template).

Either way, it still causes additional bloat that really should not be there.

[edit]This is more of a bug bear of mine having gained experiance of what happens a year down the line on a large project[/edit]
There is absolutely nothing wrong with forward declarations. In fact there are many situations where they are very useful, for example the pimpl idiom where they are used to reduce dependencies and increase security:
class MyClassImpl;class MyClass{	public:		// member functions	private:		boost::shared_ptr< MyClassImpl > pimpl_;};

Here the implementation of MyClass is hidden behind the opaque pimpl_ pointer, making MyClass a lightweight class with few dependencies. If the implementation of MyClass changes but the interface remains the same then only MyClassImpl.cpp needs recompiling.

Enigma

This topic is closed to new replies.

Advertisement