Наследование в C ++, вызывающее функции от дочерней переменной родительского класса

В C ++ у меня есть базовый класс Packet, а затем много детей APIPacket, DataIOPacket и т. Д.
Теперь я хочу сохранить входящий пакет, и так как я не знаю тип, я храню его в переменной:

Packet packet;
packet = DataIOPacket();

Но теперь DataIOPacket имеет функцию getAnalogData ();
Я не могу сделать:

packet.getAnalogData();

Поскольку пакет не имеет этой функции. В Java я думаю, что это возможно, так как фактический тип объекта, хранящегося в пакете, не теряется (это правильно?). Но в C ++ мой DataIOPacket сужается в Packed и теряет свои функции, которые не были объявлены в Packet.

Вы можете создать виртуальную функцию в пакете для каждой функции в каждом дочернем элементе. Но для меня это будет означать много функций в пакете, которые в большинстве случаев не должны вызываться. Он не имеет смысла вызывать getAnalogData () для APIPacket.

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

Вы могли бы что-то сделать с типизацией назад к DataIOPacket и APIPacket, но это тоже не кажется чистым решением.

Есть ли библиотеки, которые решают мою проблему?

Rgds,

Рул

4

Решение

Это возможно и в Java, и в C ++.
вам нужно сделать dynamic_cast для проверки типа.

 Packet* packet;
packet = new DataIOPacket();

DataIOPacket dio* = dynamic_cast<DataIOPacket*>(packet);
if (dio != 0)
{
dio->DoSomeChildMethodStuff();
}
4

Другие решения

в С ++ мой DataIOPacket сужается в Packet и теряет свои функции, которые не были объявлены в Packet

Это происходит потому, что вы назначаете объект типа DataIOPacket к объекту типа Packet, что приводит к тому, что этот объект нарезанный (увидеть Что такое нарезка объектов?).

То, что вы на самом деле ищете, это способ, которым вы могли бы узнать в время выполнения, был ли объект, с которым вы работаете, создан как экземпляр DataIOPacket, Другими словами, вы ищете Идентификация типа времени выполнения (RTTI).

Избежать нарезка, вам нужно иметь ссылку или указатель на объект. Тип этого объекта будет затем идентифицирован в время выполнения:

Packet* packet;
packet = new DataIOPacket();

сейчас packet указатель на объект типа DataIOPacket (время выполнения), но тип указателя Packet* (время компиляции). Для того, чтобы вызвать метод, который является специфическим для DataIOPacket Класс на этом объекте, компилятор должен знать, что этот указатель указывает на объект типа, который предоставляет этот метод. Правильный способ понижения указателя на полиморфный тип — использование dynamic_cast, который возвращает NULL в случае, если этот объект не может быть приведен к этому типу:

Packet* packet;
packet = new DataIOPacket();
DataIOPacket* dataIOPacket = dynamic_cast<DataIOPacket*>(packet);
if (dataIOPacket)
dataIOPacket->getAnalogData();

Обратите внимание, что это также возможно с объектами с автоматической продолжительностью хранения:

DataIOPacket packet;
Packet* pPacket = &packet;

DataIOPacket* dataIOPacket = dynamic_cast<DataIOPacket*>(pPacket);
if (dataIOPacket)
dataIOPacket->getAnalogData();

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

1

Хорошо, я понял, как некоторые люди предполагают, что необходимость динамического приведения предполагает, что моя структура неверна. Поэтому я собираюсь изменить то, что каждый тип пакетов получает свое собственное пространство для хранения. Я храню пакеты, где я их читаю, и они затем передаются в основной поток, который выполняет всю обработку. На самом деле имеет больше смысла, что вы держите тип. Мой основной поток не хочет выяснять, какой тип пакетов, поскольку он по-разному обрабатывает разные пакеты. Если вам когда-нибудь понадобится поведение, которое я описал в своем вопросе, я думаю, что динамическое приведение — путь. Но прежде чем сделать это, вы должны спросить себя, не следует ли изменить структуру. А использование динамического приведения не будет работать с объектами, поскольку они подвергаются нарезке. Работает только на указателях.

0
По вопросам рекламы ammmcru@yandex.ru
Adblock
detector