2010-10-20 2 views
0

У меня есть 3 класса:Кастинг для унаследованных классов?

class Super 
{ 
    virtual int getType() { return 1; } 
} 
class Special : public class Super 
{ 
    virtual int getType() { return 2; } 
} 
class SpecialSpecial : public class Special 
{ 
    virtual int getType() { return 3; } 
} 

И у меня есть функция, которая принимает в качестве аргумента std::vector<Super*>:

void handleClasses(std::vector<Super*> superVector) 
{ 
    foreach element in superVector //Pseudocode!! 
    { 
     if(element->getType() == 1) 
      std::cout << "Thats a SuperClass" << std::endl; 
     else if(element->getType() == 2) 
      std::cout << "Thats a SpecialClass" << std::endl; 
     else if(element->getType() == 3) 
      std::cout << "Thats a SpecialSpecialClass" << std::endl; 
    } 
} 

Там может быть пользователь, который наследует от класса Special:

class ParalellSpecial : public class Special 
{ 
    virtual int getType() { return 4; } 
} 

Теперь функция handleClasses не может понять новый класс с типом 4, но он должен иметь возможность t o использовать следующий превосходный класс (в данном случае это Special).

Как бы кто-то реализовал такую ​​вещь? Существует ли шаблон проектирования, который позволяет создать иерархический порядок классов, а следующий доступный суперкласс будет использоваться в качестве резерва, если текущий класс не может быть использован (потому что он неизвестен)?

ПРИМЕЧАНИЕ. Идентификаторы типов предназначены только для демонстрационных целей. Разумеется, есть более эффективные методы для определения класса в C++ (RTTI).

+1

Хорошее осуществление, но в чем проблема? Почему вы используете if-else-if вместо того, чтобы просто вводить реальный код в этот виртуальный метод? – sharptooth

+0

Разве вы уже этого не делаете? I.e. если тип неизвестен, вы возвращаетесь к специальному – Cratylus

+0

@userxxx: Там может быть много классов, которые неизвестны. Возможно, пользователь наследует от 'super', затем следующий наследует от другого userclass и т. Д. Также могут быть серверные методы' handleClasses', которые частично понимают пользовательские классы и т. Д. – MOnsDaR

ответ

2

2 возможные ответы здесь:

1) Если вы думаете, что вам нужно знать, какой тип объекта на самом деле, то, возможно, ваш инкапсуляция неправильно. Возможно, handleClasses() должен вызывать метод для объекта, и каждый класс должен предоставлять другую реализацию?

2) Если это одно из редких случаев, когда вам действительно нужно знать тип объекта, используйте dynamic_cast<>. Вот для чего это. E.g:

void handleClasses(std::vector<Super*> superVector) 
{ 
    foreach element in superVector //Pseudocode!! 
    { 
     if(dynamic_cast<SpecialSpecial *>(element) != 0) 
      // SpecialSpecial or a subclass of SpecialSpecial 
      std::cout << "Thats a SpecialSpecialClass" << std::endl; 
     else if(dynamic_cast<Special *>(element) != 0) 
      // Special or a subclass of Special 
      std::cout << "Thats a SpecialClass" << std::endl; 
     else 
      // Super or a subclass of Super 
      std::cout << "Thats a SuperClass" << std::endl; 
    } 
} 
+0

Thats хорошая идея, я мог бы начать с попытки 'dynamic_cast' в' Супер'. Если это сработает, я попробую 'dynamic_cast' в подкласс супер и т. Д. Это будет продолжаться, пока я не найду самый специализированный класс в моем дереве. Все, что под этим не будет просто бросать. – MOnsDaR

0

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

Другой идеей было бы создать глобальный реестр типов, который знает о связях типов. Затем вы можете использовать реестр для перемещения по иерархии, пока не найдете тип, который вы можете обрабатывать. Реестр может быть просто DAG с идентификаторами типов как узлы.

+0

Я отредактировал оригинальный вопрос. Вышеприведенный код должен просто помочь понять проблему, это не компилируемый код reallife. Просто назовите это Pseudocode вместо действительного C++ - Code, если это поможет. – MOnsDaR

0

Первое решение, чтобы получить вещь: перемещение

Ребенок-классы интегрировать тип суперкласса в свой собственный Type-ID.
- Super получает тип == 1
- Special Получает тип == 21
- SpecialSpecial Получает тип == 321
- ParalellSpecial Получает тип == 421

handleClasses теперь проверяет, если первая цифра известна (это не относится к ParalellSpecial. затем он проверяет, если вторая цифра известна (что имеет место), а затем выводит сообщение, относящееся (или делает то, что он хочет сделать, например, литье из Super в Special)

Эта концепция имеет большой недостаток, что на уровне иерархии может быть только 10 классов. Я думаю, что концепция типов-идентификаторов не оптимальна.

Думайте, что есть лучшие доступные решения.

Смежные вопросы