Безопасность литья между указателями двух одинаковых классов? - PullRequest
9 голосов
/ 14 октября 2011

Допустим, у меня есть два разных класса, каждый из которых представляет данные 2D-координат одним и тем же внутренним способом, как показано ниже:

class LibA_Vertex{
    public:
    // ... constructors and various methods, operator overloads
    float x, y
};

class LibB_Vertex{
    public:
    // ... same usage and internal data as LibA, but with different methods
    float x, y
};


void foobar(){
    LibA_Vertex * verticesA = new LibA_Vertex[1000];
    verticesA[50].y = 9;
    LibB_Vertex * verticesB = reinterpret_cast<LibB_Vertex*>( vertexA );
    print(verticesB[50].y); // should output a "9"
};

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

(Справочная информация: мне нужен простой способ торговли массивами вершин между двумя отдельными библиотеками, которые имеют идентичные классы Vertex, и я хочу избежать ненужного копирования массивов).

Ответы [ 4 ]

13 голосов
/ 14 октября 2011

C ++ 11 добавил концепцию под названием совместимый с макетом , которая применима здесь.

Два стандартного типа структуры (раздел 9) совместимый с макетом , если они имеют одинаковое количество нестатических элементов данных и соответствующие нестатические элементы данных (в порядке объявления) имеют совместимых с макетом типов (3.9).

где

Класс стандартного макета - это класс, который:

  • не имеет нестатических членов-данных типа non-standard-layoutкласс (или массив таких типов) или ссылка,
  • не имеет виртуальных функций (10.3) и виртуальных базовых классов (10.1),
  • имеет одинаковый контроль доступа (пункт 11) для всех* Нестатические члены данных,
  • не имеет базовых классов нестандартной компоновки,
  • также не имеет элементов не статических данных в наиболее производном классе и не более одного базового класса с нестандартнымичлены статических данных, или не имеет базовых классов с нестатическими членами данных, а
  • не имеет баse классы того же типа, что и первый нестатический элемент данных.

A структура стандартного макета - это класс стандартного макета , определенный с помощью ключ класса struct или ключ класса class.

A объединение стандартных макетов является стандартом -layout class , определенный с помощью class-key union.

Наконец

Указатели на cv-квалифицированные и cv-неквалифицированныеверсии (3.9.3) совместимых с макетом типов должны иметь одинаковые требования к представлению значений и выравниванию (3.11).

, что гарантирует, что reinterpret_cast может превратить указатель на один тип в указатель налюбой тип, совместимый с макетом.

1 голос
/ 14 октября 2011

Теоретически это неопределенное поведение. Однако это может работать в определенных системах / платформах.

Я бы посоветовал вам попытаться объединить 2 класса в 1. т. Е.

class Lib_Vertex{
// data (which is exactly same for both classes)
public:
// methods for LibA_Vertex
// methods for LibB_Vertex
};

Добавление методов в class не повлияет на его размер. Возможно, вам придется немного изменить свой дизайн, но оно того стоит.

1 голос
/ 14 октября 2011

Я бы обернул это преобразование в классе (так что если вам нужно сменить платформу или что-то еще, оно хотя бы локализовано в одном месте), но да, это должно быть возможно.

Вы захотите использовать reinterpret_cast, а не static_cast.

0 голосов
/ 14 октября 2011

Технически это неопределенное поведение.В действительности, если один и тот же компилятор использовался для компиляции обоих классов, они будут иметь одинаковое расположение в памяти, если поля объявлены в одном и том же порядке, имеют одинаковые типы и одинаковый уровень доступа.

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