C ++ полиморфизм и приведение типов - PullRequest
0 голосов
/ 20 сентября 2011

Я относительно новичок в C ++ и работаю над базовым движком трехмерного рендеринга, использующим OpenGL. У меня есть следующая проблема: у меня есть класс с именем GeomEntity, который является базовым классом для всех геометрических примитивов. У меня есть другой класс, называемыйDefaultMaterial, который является базовым классом для всех материалов (состоит из различных типов шейдерных программ). Потому что у меня будет много типов материалов, таких как: ColorMaterial, TextureMaterial, AnimatedMaterial и т. Д. Мне нужно поместить ссылку на материал в GeomEntity.класс, так что из основного приложения я могу установить любой материал с помощью этой функции:

  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);

Ответы [ 4 ]

3 голосов
/ 20 сентября 2011

В C ++ вы можете сделать это с помощью dynamic_cast, то есть, я считаю, наиболее близким эквивалентом этой функции C #:

AnimatedMaterial* panim = dynamic_cast<AnimatedMaterial*>(sphere.material);
if(panim) 
  panim->interpolateColor(timerSinceStart);
2 голосов
/ 20 сентября 2011

Если вы уверены, что sphere.material указывает на объект, с которым связан метод interpolateColor, вы можете использовать static_cast (если бы были сомнения, тогда вы бы использовали dynamic_cast). Предполагая, что класс AnimatedMaterial имеет interpolateColor метод:

static_cast<AnimatedMaterial*>(sphere.material)->interpolateColor(timerSinceStart);
2 голосов
/ 20 сентября 2011

Вы можете разыграть, это выглядело бы так:

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

Но используйте способ Блинди, он чище.


Оригинальный ответ, недействительный при редактировании вопроса:

Вы сказали:

//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*
}

При обходе полиморфных объектов вы должны использовать указатели, а не ссылки.

1 голос
/ 20 сентября 2011

Почему бы просто не использовать:

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

, поскольку animMaterial уже имеет правильный тип?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...