Как я могу конвертировать типы в C++?
Вопрос
В своем проекте я использую две разные библиотеки, и обе предоставляют базовый прямоугольник. struct
.Проблема в том, что, похоже, нет способа вставить преобразование между типами, поэтому я не могу вызвать функцию в одной библиотеке с результатом функции в другой.Если бы я был автором любого из них, я мог бы создавать преобразования извне, я не могу.
библиотека а:
typedef struct rectangle { sint16 x; sint16 y; uint16 w; uint16 h; } rectangle;
библиотека б:
class Rect {
int x; int y; int width; int height;
/* ... */
};
Теперь я не могу сделать конвертер class
, поскольку C++ будет искать преобразование только за один шаг.Вероятно, это хорошо, потому что появится много возможностей для создания новых объектов всех типов.
Я не могу создать оператор, который принимает struct
от a
и предоставляет объект class
от b
:
foo.cpp:123 error: ‘operator b::Rect(const rectangle&)’ must be a nonstatic member function
Итак, есть ли разумный способ обойти это?
редактировать:
Возможно, мне следует также отметить, что мне бы очень хотелось какое-то решение, которое сделает работу с результатом беспрепятственной, поскольку я не ожидаю, что буду таким программистом.(Хотя я согласен, олдскульное, явное преобразование было бы хорошим выбором.Другая ветка, reinterpret_cast
та же проблема..)
редактировать2:
На самом деле ни одно из предложений не отвечает на мой актуальный вопрос. Конрад Рудольф кажется, правильно.C++ на самом деле не может этого сделать.Отстой, но это правда.(Если это имеет какое-то значение, я попробую создать подклассы, как это предложено КодированиеTheWheel.
Решение
Если вы не можете изменять структуры, у вас нет альтернативы написанию функции преобразования вручную, поскольку перегрузка операторов преобразования работает только внутри тела класса.Другого пути нет.
Другие советы
Создайте промежуточный тип прокладки "RectangleEx
", а также определить пользовательские преобразования в/из сторонних типов строк.Всякий раз, когда вы обращаетесь к любому из API, делайте это через класс прокладки.
Другим способом было бы получить class
от любого rect
или Rectangle
, и вставьте туда преобразования/конструкторы.
Не уверен, насколько это разумно, но как насчет чего-то вроде этого:
class R
{
public:
R(const rectangle& r) { ... };
R(const Rect& r) { ... };
operator rectangle() const { return ...; }
operator Rect() const { return ...; }
private:
...
};
Тогда вы можете просто обернуть каждый rectangle
в R()
и «правильное дело» произойдет.
В вашем случае это может быть неосуществимо, но я видел, как люди использовали небольшой препроцессор-foo для обеспечения совместимости типов.
Даже это предполагает, что вы создаете одну или обе библиотеки.
Также возможно, что вы вообще не хотите этого делать, а хотите пересмотреть какое-то раннее решение.Или нет.
Почему бы не что-то простое, например:(обратите внимание, что это может/вероятно не скомпилируется), но вы поняли...
private Rect* convert(const rectangle& src)
{
return new Rect(src.x,src.y,src.w,src.h);
}
int main()
{
rectangle r;
r.x = 1;
r.y = 2;
r.w = 3;
r.h = 4;
Rect* foo = convert(&r);
...
delete foo;
}
РЕДАКТИРОВАТЬ: Похоже, у нас с Коко та же идея.
Если struct
внутри были одинаковыми, вы могли бы сделать reinterpret_cast
;однако, поскольку похоже, что у вас есть 16-битные и 32-битные поля, вы, вероятно, застряли при преобразовании при каждом вызове или написании оболочек для всех функций одной из библиотек.
Может быть, вы могли бы попробовать это с перегрузкой операторов?(Может быть, оператор =, который не является методом вашего класса)?
Оператор Rect= (const Rect&,const прямоугольник&)
Подробнее об этом читайте в языке программирования C++ Бьярна Страуструпа или, может быть, на этой странице: http://www.cs.caltech.edu/courses/cs11/material/cpp/donnie/cpp-ops.html