I am relatively new to C++ and I have been working on a basic 3D rendering engine using OpenGL.I have the following issue: I have a class called GeomEntity which is the base class for all geometry primitives.I have another class called DefaultMaterial which is the base class for all materials(consists of different types of shader programs) .Because I am going to have many types of materials like :ColorMaterial,TextureMaterial,AnimatedMaterial and so on I need to put a reference to the material in GeomEntity class so that from the main app I can set any of the material with this function:
void GeomEntity ::addMaterial (const DefaultMaterial *mat){
material=mat;////material is the member variable pointer of type DefaultMaterial
}
But the thing is that although all of those materials are derived from the DefaultMaterial they all have got their unique methods which I can't trigger if I reference them to the variable of DefaultMaterial by default. So for example in the main application:
Sphere sphere;
....
sphere.addMaterial(&animMaterial);///of type AnimatedMaterial
sphere.material->interpolateColor(timerSinceStart);
///doesn't happen anything as the sphere.material is
/// of type DefaultMaterial that has no interpolateCol开发者_StackOverflowor() method
I know I have can use templates or casts but I would like to hear about the best practices of this kind of polymorphism in C++ .In Java or C# I would really use something like this:
((AnimatedMaterial)sphere.material).interpolateColor(timerSinceStart);
In C++ you can do this using dynamic_cast, that is I believe closest equivalent of that C# feature:
AnimatedMaterial* panim = dynamic_cast<AnimatedMaterial*>(sphere.material);
if(panim)
panim->interpolateColor(timerSinceStart);
If you are sure that sphere.material
points to an object that has interpolateColor
method associated with it, you can use static_cast
(if there were doubts, then you would use dynamic_cast
). So assuming that AnimatedMaterial
class has interpolateColor
method:
static_cast<AnimatedMaterial*>(sphere.material)->interpolateColor(timerSinceStart);
You can cast, it would look like:
static_cast<AnimatedMaterial*>(sphere.material)->interpolateColor(...);
But use Blindy's way, it's cleaner.
Original answer made invalid by question edit:
You said:
//material is the member variable pointer of type DefaultMaterial
Looking at the way you're using it, it's not actually a pointer. If it were, everything would be working properly.
void GeomEntity::addMaterial( DefaultMaterial *mat )
{
material = mat; // material is the member variable pointer of type DefaultMaterial*
}
When passing around polymorphic objects, you should be using pointers, not references.
Why not simply use:
Sphere sphere;
//....
sphere.addMaterial(*animMaterial); //of type AnimatedMaterial
animMaterial->interpolateColor(timerSinceStart);
since animMaterial
is already of the right type?
精彩评论