0

I am quite new to c++ and I am just trying to get to grips with the pointers and syntaxes that it uses. I have been using for about 6 weeks and I am making a small game engine on it just to try and get better at programming. I currently have a list that will hold Transforms, a superclass that i have made to hold objects basic characteristics. I have Two subclasses for my transform, GameObject and Primitive.

Primitives are basic shapes such as planes and cubes where as GameObjects are objects that contain children and a parent. I have made it in such a way that transforms can be parented and have children so both of these subclasses can be connected for moving transformations and such.

This all works through polymorphism but when i try to call the renderer on my list of transforms it will call the superclass version of Update that resides in transform. Which it shouldn't in theory as in other languages. So I have had to try and cast them to their respective classes, which is a little messier but I have run into a problem.

Its irritating that i cant just do casts like (Primtive)transform. It also screws up the variable primitiveType, it makes it some weird large number.

for (Transform go : gameObjects)
{

    if (go.type == TYPE_MESH)
    {

        Transform* t = new Transform();
        t = &go;
        Primitive* primitive = static_cast<Primitive*>(t);

        if (primitive->primitiveType == P_CUBE)
        {
            Cube* cube = static_cast<Cube*>(primitive);
            cube->Update();
        }
        //delete t;
    }

    if (go.type == TYPE_GAMEOBJECT)
    {

    }

The reason I have commented out "delete t;" is it breaks the compiler for some reason, when it really shouldn't as far as I can see. So currently it causes a small memory leak.

What is going on? All my update functions are writen with virtual void Update() so shouldnt it not matter what form the variable is in? be it a transform or a primitive, the function should call whatever code was applied to it in the first place?

sehe
  • 374,641
  • 47
  • 450
  • 633
  • 1
    You should start here: http://stackoverflow.com/questions/274626/what-is-object-slicing , https://en.wikipedia.org/wiki/Object_slicing – Igor Tandetnik Oct 17 '15 at 19:31
  • Just curious, what do you mean by "breaks the compiler"? – awksp Oct 17 '15 at 19:32
  • 2
    `Transform* t = new Transform(); t = &go;` You just overwrote the pointer to the object allocated with `new`. No wonder your `delete` dies horribly - what do you intend to delete?? – Roddy Oct 17 '15 at 19:33
  • Rule Number 1: It's your problem. Rule Number 2: It's usually your fault. [Select Isn't Broken](http://blog.codinghorror.com/the-first-rule-of-programming-its-always-your-fault/) – sehe Oct 17 '15 at 19:35
  • Also, what *exactly* is the type of `gameobjects`. Hopefully, a container of *pointers*... – Roddy Oct 17 '15 at 19:36
  • @sehe is just parrotting the usual advice. – Martin James Oct 17 '15 at 19:38
  • "I have been using for about 6 weeks" - what is this, coders anonymous? I've been using for years, and most of my friends and family won't talk to me anymore because I demand they document their preconditions. – Kerrek SB Oct 17 '15 at 19:46
  • When i type delete t; (the pointer i created it greys out the entire line and throws an error. – Jamie Gear Oct 18 '15 at 20:02
  • Kerrek, if you dont have anything constructive to add then dont post at all... – Jamie Gear Oct 18 '15 at 20:03

2 Answers2

1

There are many issues here, but at the very least you need:

  • virtual types (need to have at least 1 virtual member, e.g. the destructor)
  • use dynamic_cast unless you know the type statically. You can have it throw exception (on reference-cast) or return nullptr (on pointer cast)
sehe
  • 374,641
  • 47
  • 450
  • 633
0

You're engaging in a whole bunch of unnecessary cast/new/delete gymnastics, which makes me wonder about the data structures you're actually using.

Polymorphism requires you to have containers that store pointers to objects, rather than objects themselves (because objects can be differing sizes). I hope you're doing that, otherwise you're getting object slicing.

Once you have that sorted,the messy code turns into this.

for (Transform *t : gameObjects)
{  
    if (t->type == TYPE_MESH)
    {
       Cube* cube = dynamic_cast<Cube*>(t);
       if (cube)
          cube->Update();
    }
    ...

Also, the if (t->Type == ..) is bit of a code smell. Can't you use dynamic cast to determine the object type?

Roddy
  • 66,617
  • 42
  • 165
  • 277
  • Using a `dynamic_cast` instead of type tags is not better at all. It is still type-switching. – Jens Oct 17 '15 at 20:44
  • Okay first off, i have been told for games it usually is better to store the objects instead of pointers to object. I dont know if i have been mislead here but i do think a container of pointers makes more sense than containing the objects themselves. The gameObjects variable stores a list of Transforms, which GameObject and Primitive are children to. – Jamie Gear Oct 18 '15 at 20:00
  • Thanks for all your input. It solved SO many issues after i changed my container to store a list of pointers. It is now correctly behaving in a pollymorphic way. – Jamie Gear Oct 18 '15 at 20:11