Advertisement

Short question on polymorphism

Started by November 11, 2016 09:22 AM
6 comments, last by frob 7 years, 10 months ago

Hi all,

I was reading Game engine architecture and with that, brushing up some coding theory.

If I recall correct, polymorphism can help you for example to achieve the following:

- create a parent class with a virtual function, that needs to implemented in child/ inherited classes

- let's take a shape for example

- I have a triangle and square class implementing their own Draw function, like declared a virtual function in the shape class

Now my question is, how do I iterate through all child class objects?

Simplified code:


class Shape
{
public:
	unsigned int someVar;

	virtual void Draw();
};


class Triangle : public Shape
{
public:
	void Draw();
};

class Square : public Shape
{
public:
	void Draw();
};


// some program

std::vector<Triangle> myTriangles;
std::vector<Square> mySquares;

// generate some triangles and squares

for(size_t i=0;i<myTriangles.size();++i) myTriangles[i].Draw();
for(size_t j=0;j<mySquares.size();++j) mySquares[j].Draw();

I believe it should be possible to do the last 2 lines at once.

How would I iterate through them at once, using the advantage that polymorphism should bring here?

Crealysm game & engine development: http://www.crealysm.com

Looking for a passionate, disciplined and structured producer? PM me

IMHO having separate vectors for the triangles and squares is the right way of doing it.

Now you could instead complicate your code by having a vector of pointers to shapes, dynamically allocate each shape instead of having them inside 2 contiguous memory blocks, then iterate through them in one for-loop requiring extra pointer dereferencing and virtual calls, to slow down your program, if you really wanted, which I doubt.

Advertisement

To iterate it in single loop, store in vector pointers to objects, upcasted to the type of base class.

Objects could be created on heap, or allocated from specialized pools.

I believe your example with shapes was just a hypothetical task, and you didn't really mean to iterate small objects spread across entire heap.

You can iterate through them all at once if you store them all in the same vector. That would be a vector<Shape*>. Note that it has to be a pointer, because polymorphism in C++ is implemented via pointers. Unfortunately that now means you need to worry about memory management, so actually you probably want a vector<shared_ptr<Shape>> - or to use a better programming language ;)

In fact, in you example you could get rid of the base class entirely and gain expressiveness and performance.

Polymorphism and inheritence are powerful tools that should be used only when absolutely necessary. If things have a relationship in real life that can be modelled with inheritence is no reason to do it. Only do it if you want classes to be accessed via a common interface AND having it callable without exposing the actual classes. Good examples of this are actually pretty rare!

Thanks, this helps in understanding the principles. I'm not aiming to apply it anywhere yet, just like to understand the different options out there.

Crealysm game & engine development: http://www.crealysm.com

Looking for a passionate, disciplined and structured producer? PM me

Advertisement

Inheritance and polymorphism were originally designed as a way to easily modify existing code. Later they were used as a way to design new code.

If you had a "thing" and you needed an "new thing" that was like a "thing" but with some extra info (new data), you used inheritance.

If your "new thing" needed to calculate something differently (different methods/functions/routines), like "newthing.sizeof()", you used poymorphism to override.

Later it was discovered that inheritance was a way you can abstract hierarchical relations in the systems in your code. But it really only lends itself well to things that have an inherit hierarchy to their organization. The dreaded inheritance diamond can result in cases that are not inherently hierarchical in nature. Games are often not hierarchical in nature. For non-hierarchical situations, composition is the favored method.

So if you have a "thing" and you need a "new thing" = "thing" + "extra data", inheritance is an easy way to mod the code to get that.

But if that "extra data" is also used by other stuff in the game, odds are it should be a component, and a "new thing" = a "thing" component + an "extra data" component.

You may find that by doing this, you use polymorphism less, as the methods of a component are less likely to require overriding.

Polymorphism can be an easy way to mod the code when you need a "new thing" = "thing" with different behavior.

Norm Barrows

Rockland Software Productions

"Building PC games since 1989"

rocklandsoftware.net

PLAY CAVEMAN NOW!

http://rocklandsoftware.net/beta.php

I'm not aiming to apply it anywhere yet, just like to understand the different options out there.

Inheritance is often overused. It is designed for, and works best, when the objects are completely interchangeable. They need exactly the same interface, they need behavior that varies in fairly minor ways and with no side effects. Also generally this means using an interface that is general commands rather than specific details.

An easy example that most game programmers are familiar with, consider the Direct3D graphics interface. The interface is identical for all the cards. You don't care if the concrete class is an NvidiaGeForce980, or AmdRadeonR7250, or an IntelIris580. All you care is that it is an ID3D11Device that implements all the functionality. You can call CreatePixelShader() and it will generate a pixel shader object that works perfectly with whatever the actual implementation happens to be. All of the details are abstracted away so you don't need to call a slightly different function for each chipset. Each one is interchangeable and the programmer doesn't need to know or care about the differences.

When something is no longer perfectly compatible and perfectly changeable with an interface it needs to be in a different hierarchy. For example, if I'm dealing with a generic GameObject, as a programmer I don't care if the game object is a character avatar, a gun, a wall, a car, or an audio emitter. But I do know that because it is a GameObject I can do anything with it that I could do with any other game object.

Also, in most programming languages inheritance is either the strongest or second-strongest relationship you can give objects. In C++ the only stronger relationship is 'friend'. In Java and C# inheritance is second only to using reflected access.

Too many schools spend time teaching that the concept exists, and don't teach when and why it should (and shouldn't) be used. Generally programmers should prefer composition (has a) rather than inheritance (is a).

This topic is closed to new replies.

Advertisement