extern class objects and extern arrays?

This might be an OpenGL problem (I suspect it is) and if so I'll ask over at their forums but it might also be a problem I'm having with classes so I'll try here first.

I have a class called spaceObject which creates many objects and each one contains an array of ~1000 vertices which are then used to draw a sphere. This seems like a total waste of memory so I decided to make a single Sphere class which initializes a single vertex array. I then use the classes sole public function, draw(int), to draw the sphere.

What I would like to know is what is the proper way to do this so that I'm making only one single Sphere object. I have tried using extern but this gives unresolved external symbol errors.

An alternative approach I also considered is to have a global vertexArray variable contained within a header along with the functions that fill it. But then where to call these functions? I tried using the Sphere class (with vertexArray in the same header) to fill it but then if the array is used in other classes, it's just filled with nonsense values so I guess this comes back to the extern thing. This happens regardless of where Sphere is initiated and what I put in front of vertexArray (i.e. extern or anything else like static or nothing at all). I'm guessing the only way to do this would be perhaps to initiate a Sphere object within spaceObjects but then there's no point in that since the whole point of this was to only have one initialization.

The reason I suspect this is an OpenGL issue (state machine type problem) is that I can see that the vertex arrays are being filled but nothing is drawn. Then again they may only being filled within the Sphere header and nothing else so when I call them the reason they're not tbeing drawn is that they are being drawn but at nonsense values.

Some pseudocode to show approches although I think above is self explanatory...

- Sphere class where the draw method is called from another class

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Sphere
{
public:
    Sphere();

    void draw(unsigned int depth);

private:
    float vertexArray[3840][3];
    float texCoords[3840][2];

    // functions go here that fill above arrays
};

// extern Sphere sphere??
// Sphere sphere?? 


Sphere class fills the global arrays contained in the same header file.
These are then used in other classes that #include the sphere header.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
float vertexArray[3840][3]; // extern?!?
float texCoords[3840][2];

class Sphere
{
public:
    Sphere();

    void draw(unsigned int depth);

private:
    // functions go here that fill the global arrays
};

// Where to declare sphere now? 


No classes, just functions, that fill the arrays.

1
2
3
4
5
float vertexArray[3840][3]; // extern?!?
float texCoords[3840][2];

// functions go here that fill the global arrays
// Where should they be called? 
Last edited on
I think you probably want something like this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Sphere
{
public:
    Sphere();

    void draw(unsigned int depth);

private:
    float vertexArray[3840][3];
    float texCoords[3840][2];

    // functions go here that fill above arrays
};

extern Sphere sphere; // yes
// Sphere sphere?? // no put this in your source file Sphere.cpp along with your Sphere function code 


You put extern Sphere sphere; in the header file because it is just a declaration that somewhere there is a Sphere called sphere.

You put Sphere sphere in a source file because it needs to exist somewhere where it will be created by the compiler as a real object.
Ohhhhhhhhh of course extern doesn't actually create an instance of Sphere I see! I never even thought of that despite having a constants.h header filled with externs with the .cpp having all the value declarations.

Thank you.
If you would like to ensure that a class is instantiated only once, then I would use the singleton pattern (well, it's the purpose of this pattern :) ):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
class Sphere
{
public:
    static void init() { if (_instance == 0) _instance = new Sphere(); }
    static void term() { delete _instance; }

    // Here you have some options, like automatically initializing, 
    // or throwing an exception etc. if init() has not been called
    static Sphere* instance() { return _instance; } 


    void draw(unsigned int depth);

private:
    // Hide constructor
    Sphere(); 
    // Hide copy constructor (no implementation needed)
    Sphere(const Sphere&); 
    // Hide assignment operator (no implementation needed)
    Sphere& operator=(const Sphere&); 

    // Your one and only instance of the class
    static Sphere* _instance;

    float vertexArray[3840][3];
    float texCoords[3840][2];

    // functions go here that fill above arrays
};


In your source file:
Sphere* Sphere::_instance = 0; // same as with extern Sphere sphere;

Using the sphere functions somewhere in other code:
Sphere::instance()->draw();

And don't forget to init the Sphere class somewhere in your code (or make it automatic on first call of instance()). Call to term() is necessary to avoid mem leak.

Having a singleton class is better than an extern variable because you ensure that you have exactly one instance of the class, and you have more precise control of when the single instance is initialized (say, you may want glInit() to be called before glGenBuffers() you might use in Sphere constructor).

Hope that was a tiny bit useful :)
Last edited on
Topic archived. No new replies allowed.