开发者

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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜