Порядок приведения для унаследованных классов? - PullRequest
0 голосов
/ 20 октября 2010

У меня есть 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, но она должна иметь возможность использовать следующий улучшенный класс (в данном случае это Special).

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

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

Ответы [ 3 ]

2 голосов
/ 20 октября 2010

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

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

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

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 голосов
/ 20 октября 2010

Первое решение, чтобы заставить вещи двигаться:

Дочерние классы объединяют тип суперклассов в свои собственные Type-ID.
- Super получает тип == 1
- Special получает тип == 21
- SpecialSpecial получает тип == 321
- ParalellSpecial получает тип == 421

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

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

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

0 голосов
/ 20 октября 2010

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

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

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