Редактировать: Я только что понял гораздо более простой способ задать этот вопрос:
Учитывая следующие две структуры:
class Thing {public: int a; public: int b; public: int c;} class Thing {public: int a, private: int b; public: int c;}
Являются ли участники
a
,b
, а такжеc
гарантированно будет в том же порядке в памяти для обоих этих определений?
Допустим, у нас есть этот код C ++ в fileA.cpp
:
class Thing
{
public:
int a;
double num;
Thing()
{
b = 10;
}
float getB()
{
return b;
}
private:
float b;
Thing * other;
}
void doSomething(Thing thing);
int main()
{
Thing thing;
doSomething(thing);
std::cout << thing.b;
}
И скажем, у нас есть этот код в fileB.cpp
:
class Thing
{
public:
int a;
double num;
Thing()
{
b = 10;
}
float getB()
{
return b;
}
float b;
private:
Thing * other;
}
void doSomething(Thing thing)
{
thing.b = 30;
}
Предполагая, что компилятор не будет жаловаться, будет ли этот код работать так, как ожидалось? Является ли расположение данных структуры независимым от того, являются ли определенные компоненты общедоступными, частными или защищенными?
Редактировать: Чтобы сделать это более очевидным, единственное различие между двумя определениями Thing
тот факт, что float b;
является частным в fileA.cpp
но публика в fileB.cpp
,
Стандарт не дает такой гарантии. У вас есть гарантии на макет только для стандартных классов:
Класс стандартного макета — это класс, который:
- не имеет нестатических членов-данных типа нестандартного класса макета (или массива таких типов) или ссылки,
- не имеет виртуальных функций (10.3) и виртуальных базовых классов (10.1),
- имеет одинаковый контроль доступа (пункт 11) для всех нестатических элементов данных,
- не имеет базовых классов нестандартной компоновки,
- либо не имеет нестатических членов данных в самом производном классе и не более одного базового класса с
нестатические члены данных, или не имеет базовых классов с нестатическими членами данных, и- не имеет базовых классов того же типа, что и первый нестатический член данных.
(C ++ 14, [класс] №7)
Если класс является стандартным макетом, его макет хорошо определен (и два стандартных класса макета, которые имеют совместимую с макетом начальную последовательность, могут читать элементы, совместимые с макетом друг друга, через union
).
Однако здесь это не так, так как у вас разные спецификаторы доступа по всему классу. В частности, прямо указано, что
Порядок распределения нестатических элементов данных с различным контролем доступа не определен
(C ++ 14, [class.mem] ¶13)
Что, как говорится, Я никогда не работал с каким-либо реальным компилятором, который когда-либо использовал эту гибкость, предлагаемую стандартом — каждый известный мне компилятор использует спецификаторы доступа для проверок во время компиляции, но полностью игнорирует их в том, что касается компоновки членов.
Других решений пока нет …