Конечно, ответ «нет», потому что люди, которые написали это, очень много думали об этом, однако я хочу знать, почему.
Учитывая, что классы (без шаблонов) часто объявляются в файлах заголовков, которые затем включаются в несколько файлов, которые компилируются отдельно, рассмотрите эти два файла:
файл1.с
#include <cstddef>
struct Foo {
public:
int pub;
private:
int priv;
};
size_t getsize1(Foo const &foo) {
return sizeof(foo);
}
файл2.с
#include <cstddef>
struct Foo {
public:
int pub;
private:
int priv;
};
size_t getsize2(Foo const &foo) {
return sizeof(foo);
}
В общем случае Foo будет объявлен в заголовочном файле и включен в оба, но эффект будет таким, как показано выше. (То есть включение заголовка — это не волшебство, оно просто помещает содержимое заголовков в эту строку.) Мы можем скомпилировать оба и связать их со следующим:
main.cc
#include <iostream>
struct Foo {
public:
int pub;
private:
int priv;
};
size_t getsize1(Foo const &);
size_t getsize2(Foo const &);
int main() {
Foo foo;
std::cout << getsize1(foo) << ", " << getsize2(foo) << ", " << sizeof(foo) << '\n';
}
Один из способов сделать это — использовать g++:
g++ -std=c++11 -c -Wall file1.cc
g++ -std=c++11 -c -Wall file2.cc
g++ -std=c++11 -c -Wall main.cc
g++ -std=c++11 -Wall *.o -o main
И (в моей архитектуре и среде) это показывает: 8, 8, 8. Sizeof одинаковы для каждой компиляции file1.cc, file2.cc и main.cc.
Но гарантирует ли это стандарт c++11, действительно можно ли рассчитывать на совместимость макета со всеми тремя Foo? Foo содержит как частные, так и общедоступные поля, поэтому это не структура стандартного макета, как определено в пункте 9, п. 7 стандарта С++ 11 (рабочий проект):
Класс стандартной компоновки — это класс, который:
- не имеет нестатических элементов данных типа класса нестандартного макета (или массива таких типов) или ссылки,
- не имеет виртуальных функций (10.3) и виртуальных базовых классов (10.1),
- имеет одинаковый контроль доступа (пункт 11) для всех нестатических элементов данных,
- не имеет базовых классов нестандартной компоновки,
- либо не имеет нестатических элементов данных в самом производном классе и не более одного базового класса с нестатическими элементами данных, либо не имеет базовых классов с нестатическими элементами данных, и
- не имеет базовых классов того же типа, что и первый нестатический член данных.
Поскольку мы используем структуры, и, чтобы быть тщательным, следующий параграф говорит:
Структура стандартного макета — это класс стандартного макета, определенный с помощью структуры ключа класса или класса ключа класса. Объединение стандартного макета — это класс стандартного макета, определенный с помощью объединения классов и ключей.
Насколько мне известно, стандарт определяет совместимость макетов только между структурами в стандартном макете (пункт 9.2, пар. 18).
Два типа структуры стандартной компоновки (раздел 9) являются компоновочно-совместимыми, если они имеют одинаковое количество нестатических элементов данных, а соответствующие нестатические элементы данных (в порядке объявления) имеют типы, совместимые с компоновкой (3.9).
Так гарантируется, что все три Foo совместимы с макетом, и, что более важно, почему?
Почему (недетерминированный) компилятор, который создает разные макеты для Foo во время компиляции, не может быть компилятором С++ 11?
Foo
относятся к одному и тому же объекту, который должен иметь одинаковый набор свойств во всех единицах перевода. С этой целью все определения должны быть идентичными токен для токена, а токены должны иметь одинаковое значение; в противном случае программа неправильно сформирована, диагностика не требуется. Подробнее см. 3.2/5. - person Igor Tandetnik   schedule 23.10.2014