Is it possible to truncate an array of derived classes into an array of base classes in C++?
I'm making an application which uses OpenGL and currently store an array of objects that should be rendered each frame which look something like this:
class Object {
private:
float x;
float y;
public:
void func1();
void func2();
...
};
I'd like to be able to create a vertex buffer object from the array of these objects, but I can't simply pass the array since the class contains the additional functions which glBufferData
doesn't expect.
Would it be possible to separate the object class like so:
class baseObject {
public:
float x;
float y;
};
class derivedObject : public baseObject {
public:
float x;
float y;
void func1();
void func2();
...
};
and then cast an array of derivedObjects
into an array of baseObjects
using static_cast
or otherwise which c开发者_StackOverflowan then be passed to glBufferData
? Or is the only way to iterate through the array of Objects, extracting the x
and y
variables into a separate array which can then be passed to glBufferData
?
The functions in your class Object
don't actually contribute anything to the object's layout. Although the spec doesn't guarantee this, on all major compilers the in-memory representation of an object is just its fields. (If you add a virtual function into the mix, though, this isn't true). In your case, your Object
class would look indistinguishable from this struct
in memory:
struct JustObjectFields {
float x, y;
};
Because when you remove the member functions, this is what you're left with.
The reason for this is that member functions are typically compiled down to regular functions that take the this
pointer as an explicit first argument. This code is separate from any one instance of the class, and so the class size isn't affected by them. In short, you should be able to do this without using inheritance at all. Just use your raw Object
class.
You could create an array of base class pointers and manually point them to the elements in the derived class array. However, you cannot do any kind of fancy cast on the array itself because array offsets depend on knowing the actual size of each element. With pointers, this is not a problem, but with actual instances in an array, you'd run into lots of crashing when you try to access individual elements using a pointer of the wrong type.
Typecast for arrays doesn't work in such case - http://codepad.org/6DFLPPDH
In general, its impossible to transform an array of derived objects into
array of base objects without moving the data, and I guess nobody bothered
to support specifically the case where derived class only adds methods.
In fact, even array pointer cast is not very reliable - http://codepad.org/15a4cCy9
But with plain pointers its certainly not a problem - http://codepad.org/4vEK5wY1
And in your case it should be ok anyway, I guess.
Short answer: yes. If glBufferData
accepts baseObject
as a parameter, then derivedObject
may also be used, since an instance of class derivedObject
is also an instance of class baseObject
.
The issue here isn't methods/functions, but data. glBufferData
expects an instance of class baseObject
as a parameter because the method requires an object containing exactly the data members described in baseObject
. Object
is invalid as a parameter because its data members may differ from baseObject
. This could prove disastrous if the method is passed an object with invalid data.
However, by defining derivedObject
as inheriting from baseObject
, we are saying that derivedObject
IS a baseObject
plus all the data members listed in derivedObject
's definition. So, when we pass an instance of derivedObject
to glBufferData
, it can treat it like an instance of baseObject
without danger.
精彩评论