C++多态性和类型铸造

问题描述:

我对C++比较新,我一直在使用OpenGL开发基本的3D渲染引擎。我有以下问题: 我有一个名为GeomEntity的类,它是所有几何图元的基类。我有另一个名为DefaultMaterial的类,它是所有材质的基类(由不同类型的着色器程序组成)。因为我将有许多类型的材质,如:ColorMaterial,TextureMaterial,AnimatedMaterial等等,我需要放置参考GeomEntity类的材料,以便从主应用程序,我可以设置任何使用该功能的材料:C++多态性和类型铸造

void GeomEntity ::addMaterial (const DefaultMaterial *mat){ 

     material=mat;////material is the member variable pointer of type DefaultMaterial 

    } 

但事实是,虽然所有的这些材料是从DefaultMaterial派生的,它们都有独特的方法,如果我将它们默认引用到DefaultMaterial的变量,我不能触发它们。 因此,例如在主应用程序:

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 interpolateColor() method 

我知道我可以使用模板或石膏,但我想听到这种多态性在C++。在Java中的最佳做法或C#我真的使用这样的:

((AnimatedMaterial)sphere.material).interpolateColor(timerSinceStart); 

在C++中,你可以做到这一点使用dynamic_cast的,那就是我相信C#功能最接近的等效:

AnimatedMaterial* panim = dynamic_cast<AnimatedMaterial*>(sphere.material); 
if(panim) 
    panim->interpolateColor(timerSinceStart); 
+1

我认为这与我所了解的托管语言最接近。 –

为什么不能简单地用:

Sphere sphere; 
//.... 
sphere.addMaterial(*animMaterial); //of type AnimatedMaterial 
animMaterial->interpolateColor(timerSinceStart); 

因为animMaterial已经正确类型的?

+0

的GeomEntity内部的材料属性是不具有interpolateColor()方法 –

+0

@Ben福格特,你确定通用DefaultMaterial类型的?内部材料也可以作为参考(仍然很奇怪,但是..)。在材质上调用'interpolateColor'应该可以在函数外正常工作。 @迈克尔,我不知道你在说什么。 – Blindy

+0

问题发生变化后,这似乎是正确的答案。 –

你可以施放,它看起来像:

static_cast<AnimatedMaterial*>(sphere.material)->interpolateColor(...); 

但使用Blindy的方式,它的清洁。


原来的答复为无效的问题编辑:

你说:

//material is the member variable pointer of type DefaultMaterial 

在你使用它的方式来看,它实际上不是一个指针。如果是的话,一切都会正常工作。

void GeomEntity::addMaterial(DefaultMaterial *mat) 
{ 
    material = mat; // material is the member variable pointer of type DefaultMaterial* 
} 

当传递多态对象时,应该使用指针而不是引用。

+0

对不起,这是一个错字。问题不在于指针,而是当我们的属性数据类型是基类时,如何触发派生类中的方法? –

+2

@Michael IV,我不同意,真正的问题是*你为什么要这么做*?一个正确建模的OOP类层次结构不应该关心其实例的类型,它应该仅以基类作为接口来处理自身。 – Blindy

+0

@布林迪,你说得对,你说我不需要投射,如果材料引用了包含该方法的正确类>>? –

如果您确信sphere.material指向具有interpolateColor与之相关联的方法的对象,你可以使用static_cast(如果有疑问,那么你会使用dynamic_cast)。所以假设AnimatedMaterial类有interpolateColor方法:

static_cast<AnimatedMaterial*>(sphere.material)->interpolateColor(timerSinceStart);