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

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

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 ответа

Решение

Я бы сделал диаграмму классов другой: абстрактный базовый класс GeomObject, подкласс geometrygetType Accessor, а также чисто виртуальный 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));
  }
}

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

(обновлено, чтобы соответствовать обновленному вопросу)

Чтобы избежать дублирования, переместите код преобразования в одну вспомогательную функцию и позвольте 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));

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

if (g1-> type == LINE) {
  if (g2-> type == LINE) возвращает g1->distance(g2->l);
  if (g2->type == POINT) ...
}
еще...

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

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

Другие вопросы по тегам