Вопрос о наследовании C ++: больше проблем - PullRequest
2 голосов
/ 01 июня 2010

У меня есть базовый класс MessageHandler и 2 производных класса, MessageHandler_CB и MessageHandler_DQ.

Производные классы переопределяют метод handleMessage (...). MH_DQ обрабатывает сообщение и помещает результат в очередь, в то время как MH_CB обрабатывает сообщение и затем выполняет функцию обратного вызова.

Базовый класс имеет функцию статического обратного вызова, которую я передаю вместе с указателем this в библиотеку, которая вызывает статический обратный вызов, когда новое сообщение доступно для обработки.

Моя проблема возникает, когда я нахожусь в статическом обратном вызове с пустым пространством *, указывающим либо на MH_DQ, либо на MH_CB. Если я приведу его к базовому классу, то будет вызван пустой метод MessageHandler :: handleMessage (...), а не версия в соответствующем производном классе.

Как лучше всего решить эту ситуацию с точки зрения дизайна и / или какие языковые функции могут помочь мне найти решение моей проблемы?

Заранее спасибо!

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

Итак, у меня есть:

class MH {

...

static int CallBackFunction(MessageData *md, void *this_ptr) {
  ((MH *)this_ptr)->preprocess(md);
  return 1;
}

virtual int preprocess(MessageData *md) {
  // do some stuff
  . . .

  handleMessage(md);
  return 1;
}

virtual void handleMessage(MessageData *) = 0;

};

class MH_CB : public MH {

...

void handleMessage(MessageData *md) {
  // do something
  ...
}
};

class MH_DQ : public MH {
...

void handleMessage(MessageData *md) {
  // do something different
  ...
}
};

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

1020 * ТИА *

Ответы [ 4 ]

1 голос
/ 01 июня 2010

Не передавайте void * в обратном вызове - передайте указатель на базовый класс и объявите handleMessage виртуальным.

1 голос
/ 01 июня 2010

Добавьте ключевое слово virtual к объявлению / определению метода в базовом классе.

На самом деле, если метод в базовом классе никогда не должен запускаться, вы можете указать, что это чисто виртуальный , чтобы объявить его вообще без тела вместо определения пустого тела:

class MessageHandler
{
public:
    virtual void handleMessage(...) = 0;
};
1 голос
/ 01 июня 2010

Сделать исходный вызов метода виртуальным.

0 голосов
/ 01 июня 2010

Отметьте handleMessage () как виртуальный, добавив префикс void handleMessage() или любое другое объявление в базовом классе со словом virtual. Затем убедитесь, что производные классы реализуют одинаковую сигнатуру сообщения (то есть тот же тип возвращаемого значения и типы параметров).

Также - вместо void * используйте MessageHandlerBase * (или что угодно). Тогда вам не нужно кастовать. Кастинг часто является признаком логической ошибки со стороны программиста.

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