Лучший способ сохранить указатель на базовый класс, но иметь возможность использовать функции производного класса

#c #inheritance

Вопрос:

У меня есть a Cell , который может хранить объекты CellContent типа. CellContent должен быть виртуальный класс. Из CellContent меня должны выводиться классы Enemy и Item . Таким образом, идея состоит в том, чтобы сохранить указатель на CellContent внутри Cell . Вопрос в следующем: каков наилучший способ хранения указателя на производный класс в этих обстоятельствах?

Мое нынешнее решение не является элегантным, и я хочу его улучшить.

 class Cell
{
public:
  template<class T> void setCellContent(std::shared_ptr<T> cellContent)
  {
    _cellContent = std::dyanmic_pointer_cast<CellContent>(cellContent);

    if (std::is_same<T, Enemy>::value = true) {
      _cellContentType = CellContentType::ENEMY;
    } else if (std::is_same<T, Item>::value = true) {
      _cellContentType = CellContentType::ITEM;      
    }
  }

  template<class T> std::shared_ptr<T> getCellContent()
  {  
    return std::dynamic_pointer_cast<T>(_cellContent);
  }

  CellContentType getCellContentType()
  {
    return _cellContentType;
  }

  std::shared_ptr<CellContent> _cellContent;
  CellContentType _cellContentType;
}

int main()
{
  auto enemy = std::make_shared<Enemy>();

  Cell cell;
  cell.setCellContent<Enemy>(enemy);

  if (CellContentType::ENEMY == cell.getCellContentType()) {
    cell.getCellContent<Enemy>();
  } else if (CellContentType::ITEM == cell.getCellContentType()) {
    cell.getCellContent<Item>();
  }
}
 

Как я могу избежать использования if этого уродливого, если в основном?

Комментарии:

1. Нормальный полиморфизм с виртуальными функциями?

2. Выглядит как классическое нарушение LSP .

3. Как правило, данный класс должен быть рассчитан либо на динамический, либо на статический полиморфизм. Здесь удаление шаблонов и использование виртуальных функций, по-видимому, являются подходящим выбором.

4. @Phil1970, Значит, все функции, которые могут использоваться в производном классе, должны быть объявлены виртуальными в базовом классе?

5. Да, именно так работают виртуальные функции. Виртуальное наследование само по себе является сложной темой, дополнительную информацию см. в вашем учебнике. Stackoverflow на самом деле не очень хорошая замена хорошему учебнику по C .

Ответ №1:

Все функции производного класса, которые необходимо вызывать (без приведения типа базового класса к типу производного класса вручную), должны быть объявлены virtual в базовом классе (и переопределены в производном классе).