2012-06-25 1 views
1

Я работаю над небольшим фреймворком на C++ для использования в некоторых своих проектах, чтобы статически ссылаться на него как на полезную библиотеку. Я думаю, вы могли бы сравнить его с более специфичными для домена моими личными потребностями и более простой библиотекой, например, juce. Это упражнение для обучения и опыта, как и все остальное, поэтому я хотел бы потратить время на правильное и правильное понимание методы, которые я применяю. В настоящее время я работаю в Linux, но для того, чтобы код был переносимым, это позволит мне написать какой-либо конкретный код платформы для интерфейса.Лучший способ для идентификатора унаследованного класса

В настоящее время я работаю над базовой системой обмена сообщениями, которую я бы хотел разрешить для сообщений, содержащих объекты разных типов. Моя первая мысль была так:

class Message { 
    virtual std::string type; 
}; 
class DataMessage : Message { 
    std::vector<std::string> *data; 
}; 

Мой вопрос, что это лучший способ, чтобы определить, что сообщение является DataMessage, и либо брось его фактического типа, или получить доступ к данным он содержит?

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

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

Любые предложения, альтернативы или ссылки очень ценятся. Обсуждение различных подходов было бы удивительным!

Спасибо заранее, ребята.

+0

Я думаю, что типичным ответом будет «не надо». Попытайтесь определить, что сообщение должно делать абстрактным способом. Сделайте чистую виртуальную функцию-член в базе, а затем реализуйте ее по-разному, подходящую для производных типов. –

+0

Скорее всего, я смотрю на это довольно наивно, поскольку я все еще участвую. В качестве примера, как бы вы изменили следующее: – StillLearningCPP

+0

Извините за двойной пост: Объект DataProcessor контролирует очередь входящего сообщения для управления его состоянием. Он ищет ControlMessage, содержащий перечисление (START, STOP) или FeedbackMessage, содержащие некоторые данные для настройки внутренней модели. Вместо того чтобы предоставлять доступ ко внутренним функциям, я бы хотел, чтобы класс DataProcessor обрабатывал обратные вызовы динамически. – StillLearningCPP

ответ

2

Вы можете использовать DataMessage* pDataMessage = dynamic_cast<DataMessage*>(pMessage). pDataMessage будет действителен только в том случае, если pMessage является объектом DataMessage. В противном случае это будет NULL.

+0

После некоторого чтения, похоже, что кастинг не так плох, как некоторые люди делают это. Скорее всего, я пойду. Еще раз спасибо за Ваш ответ. – StillLearningCPP

+1

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

+1

Динамический литой может быть не так «плохо», но обычно это намек на субоптимальный дизайн. Всякий раз, когда вы используете иерархию наследования, но нужно перебирать возможные производные классы, что-то не совсем правильно. –

2

Используйте оператор typeid. Это часть C++ RTTI. Поддержка почти всех компиляторов. Хотя, если это ваша собственная структура, подход с полем данных (лучше типа перечисления) также не так уж плох.

+0

Я не понимал, что есть оператор типа, это тоже может быть полезно. Спасибо за информацию, я прочитаю немного больше, прежде чем принимать какие-либо решения. – StillLearningCPP

3

Мой вопрос, что это лучший способ, чтобы определить, что сообщение является DataMessage, и либо бросьте его фактический тип, или получить доступ к данным он содержит?

Вы не должны этого делать!
Как только вы это сделаете, вы делаете свой дизайн слабым. Вы по существу в конечном итоге разорвать один из основного принципа SOLID paradigm, то "Liskov Substitution Principle".
Обратите внимание, что в любом месте вашего кода, если вы выполняете действия в зависимости от конкретного типа объекта, который вы кодируете для реализации, а не интерфейса. Основным направлением проектирования является:
«Код для интерфейса не для реализации."
Если начать кодирование к конкретным типам вашему код становится все труднее поддерживать и более плотно coupled.Each раз, когда вы хотели бы, чтобы добавить новый производный класс код даже ломается дальше, и вы потеряете великодушие.

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

Возможно, вы захотите ознакомиться с хорошими картинами, такими как Template method pattern который может послужить вам хорошо.

+0

Как уже упоминалось выше, мое внимание сосредоточено на звуковом дизайне над «просто сделанным». Я нацелен на то, чтобы это была личная рамка, в которой я могу расширить свое будущее, но не путающую неразбериху, которую только я могу понять. Я думал об этом как об общем механизме передачи данных, который позволяет избежать обратных вызовов. Разрешить объектам предоставлять интерфейс для связи друг с другом, возможно, даже в среде плагина. Я закрою этот вопрос и последую за ним, чтобы избежать проблем, которые вы описали. Спасибо кучи за ваш ответ и помощь. – StillLearningCPP

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