Таблица отправки в C ++ - PullRequest
       7

Таблица отправки в C ++

3 голосов
/ 16 января 2010

Предположим, у меня есть что-то вроде следующего:

class Point : geometry {
   ...
   Point(double x, double y) {
   }
   double distanceTo(Line) {
   }
   double distanceTo(Point) {
   }
}
class Line : geometry {
   ...
   Line(double x, double y, double slopex, double slopey) {
   }
   double distanceTo(Line) {
   }
   double distanceTo(Point) {
   }
}
struct point_t {
    double x, y;
}
struct line_t {
    double x, y, slope_x, slope_y;
}
struct Geom_Object_t {
   int type;
   union {
       point_t p;
       line_t l;
   } geom;
}

Мне интересно, как лучше определить таблицу диспетчеризации для такой функции, как

double distanceTo(Geom_Object_t * geom1, Geom_Object_t * geom2) {
}

Классы написаны на C ++, но функция distanceTo и структура должны быть расширены до C

спасибо

Ответы [ 4 ]

3 голосов
/ 16 января 2010

Я бы сделал диаграмму классов другой: абстрактный базовый класс GeomObject, подклассы geometry (с аксессором getType, а также чисто виртуальные distanceTo перегрузки) и конкретные подклассы Line и Point из GeomObject (с переопределением метода доступа и перегрузками). Необходимость "extern C" функции double distanceTo не является проблемой, так как вы все равно не говорите о перегрузках этой функции : вы просто хотите вернуть geom1.distanceTo(x) (позволить виртуальной таблице сделать это часть работы ;-) где x - это подходящее приведение, например, с учетом диаграммы классов, которую я объяснил:

extern "C"
double distanceTo(Geom_Object_t * geom1, Geom_Object_t * geom2) {
  if(geom2->getType() == POINT_TYPE) {
    return geom1->distanceTo(static_cast<Point*>(geom2));
  } else {
    return geom1->distanceTo(static_cast<Line*>(geom2));
  }
}
2 голосов
/ 16 января 2010

Я бы использовал двойную отправку с шаблоном Visitor . Тогда вам нужно всего лишь два указателя на geometry объекты и позволить двойной диспетчеризации вызвать соответствующую виртуальную функцию distanceTo, основанную на реальных динамических типах двух объектов, что вы можете сделать из своей функции C.

1 голос
/ 16 января 2010

(обновлено в соответствии с обновленным вопросом)

Чтобы избежать дублирования, переместите код преобразования в одну вспомогательную функцию и позвольте C ++ выполнить остальную работу:

geometry makeg(Geom_Object_t* g) {
    switch(g->type) {
         case TYPE_POINT: return Point(g->geom.p.x, g->geom.p.y);
         case TYPE_LINE : return Line(g->geom.l.x, g->geom.l.y, g->geom.l.slope_x, g->geom.l.slope_y);
         // ...
    }
}

makeg(geom1).distanceTo(makeg(geom2));
0 голосов
/ 16 января 2010

не могли бы вы сделать что-то простое, как:

if (g1->type == LINE) {
  if (g2->type == LINE) return g1->distance(g2->l);
  if (g2->type == POINT) ...
}
else ...

вы можете реализовать эту часть в C ++ и выставить функцию через extern "C"

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

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