Совместимость классов или структур C ++ с struct C - PullRequest
6 голосов
/ 16 сентября 2009

Можно ли написать класс или структуру C ++, полностью совместимые с структурой C. Под совместимостью я подразумеваю размер объекта и места в памяти переменных. Я знаю, что зло использовать *(point*)&pnt или даже (float*)&pnt (в другом случае, когда переменные являются числами с плавающей точкой), но считаю, что это действительно необходимо для повышения производительности. Нелогично использовать обычный оператор приведения типов миллион раз в секунду.

Возьмите этот пример

Class Point {
    long x,y;
    Point(long x, long y) {
        this->x=x;
        this->y=y;
    }

    float Distance(Point &point) {
        return ....;
    }
};

C версия представляет собой структуру POD

struct point {
    long x,y;
};

Ответы [ 7 ]

19 голосов
/ 16 сентября 2009

Самое чистое, что нужно было сделать, это наследовать от структуры C:

struct point
{
    long x, y;
};

class Point : public struct point
{
  public:
    Point(long x, long y)
        {    this->x=x; this->y=y; }

    float Distance(Point &point)
        {                return ....;        }
}

Компилятор C ++ гарантирует, что точка структуры стиля C имеет ту же компоновку, что и компилятор C. Класс C ++ Point наследует этот макет для своей части базового класса (и, поскольку он не добавляет данных или виртуальных членов, он будет иметь такой же макет). Указатель на класс Point будет преобразован в указатель на struct point без приведения, поскольку преобразование в указатель базового класса всегда поддерживается. Таким образом, вы можете использовать объекты класса Point и свободно передавать им указатели на функции C, ожидающие указатель на struct point.

Конечно, если уже существует файл заголовка C, определяющий точку структуры, то вы можете просто включить это вместо повторения определения.

8 голосов
/ 16 сентября 2009

Да.

  • Используйте одни и те же типы в одном и том же порядке на обоих языках
  • Убедитесь, что в классе нет ничего виртуального (чтобы на передней панели не было указателя vtable)
  • В зависимости от используемых компиляторов вам может потребоваться изменить структуру структуры (обычно с прагмами), чтобы обеспечить совместимость.

(редактирование)

  • Кроме того, вы должны позаботиться о том, чтобы проверить sizeof () типов с вашими компиляторами. Например, я столкнулся с компилятором, который хранил шорты как 32-битные значения (когда большинство будет использовать 16). Более распространенным случаем является то, что int обычно будет 32-разрядным в 32-разрядной архитектуре и 64-разрядным в 64-разрядной архитектуре.
5 голосов
/ 16 сентября 2009

POD относится к C ++. Вы можете иметь функции-члены. "Тип POD в C ++ - это агрегатный класс, который содержит только типы POD в качестве членов, не имеет пользовательского деструктора, пользовательского оператора назначения копирования и нестатических членов типа указатель на член"

Вы должны спроектировать свои структуры данных POD таким образом, чтобы они имели естественное выравнивание, а затем их можно было передавать между программами, созданными разными компиляторами на разных архитектурах. При естественном выравнивании смещение в памяти любого члена делится на размер этого члена. То есть: число с плавающей запятой расположено по адресу, который делится на 4, двойное - по адресу, кратному 8. Если вы объявляете символ, за которым следует число с плавающей запятой, большинство архитектур будут заполнять 3 байта, но некоторые могут предположительно заполнить 1 байт. Если вы объявите float с последующим символом, все компиляторы (я должен добавить источник для этого утверждения, извините) не будут заполнены вообще.

1 голос
/ 16 сентября 2009

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

Имейте в виду, что если у вас есть пустая структура или члены данных, которые являются пустыми структурами, они имеют разные размеры в C и C ++. В C sizeof (empty-struct) == 0, хотя в C99 пустые структуры не допускаются (но могут поддерживаться в любом случае как «расширение компилятора»). В C ++ sizeof (empty-struct)! = 0 (типичное значение - 1).

1 голос
/ 16 сентября 2009

C и C ++ - это разные языки, но в C ++ всегда подразумевалось, что у вас может быть реализация, которая поддерживает оба языка в двоичной форме. Поскольку это разные языки, всегда подробно описывается, поддерживается ли это компилятором. Как правило, поставщики, предоставляющие компилятор C и C ++ (или один компилятор с двумя режимами), поддерживают полную совместимость для передачи POD-структур (и указателей на POD-Struct ) между C ++ код и код С.

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

Вкратце: проверьте документацию вашего компилятора.

0 голосов
/ 16 сентября 2009

В дополнение к другим ответам, я бы точно не вставлял никаких спецификаторов доступа (public :, private: etc) в ваш класс / структуру C ++. IIRC компилятору разрешено переупорядочивать блоки переменных-членов в соответствии с видимостью, так что private: int a; pubic: int b; может получить замену a и b. Смотрите, например, эту ссылку: http://www.embedded.com/design/218600150?printable=true
Я признаю, что был озадачен тем, почему определение POD не включает запрет на это.

0 голосов
/ 16 сентября 2009

Пока ваш класс не проявляет некоторые продвинутые черты своего рода, такие как выращивание чего-то виртуального, он должен быть почти такой же структуры.

Кроме того, вы можете изменить Class (который в любом случае недействителен из-за использования заглавных букв) на struct без какого-либо вреда. За исключением того, что участники станут публичными (теперь они приватные).

Но теперь, когда я думаю о том, что вы говорите о преобразовании типов ... Невозможно превратить float в long, представляющее то же значение, или наоборот, приведя тип указателя. Надеюсь, вам нужны эти указатели только для того, чтобы что-то передвигать.

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