Могу ли я определить, какие типы при использовании в качестве базового класса потенциально перекрывают свой производный класс - PullRequest
4 голосов
/ 22 января 2020

Рассмотрим следующий класс:

class intchar {
    int x;
    char y;
};

Он имеет размер 8 на всех основных компиляторах на x86.

Рассмотрим теперь производный класс:

struct derived : intchar {
    char z;
};

На g cc и clang для Linux 1 этот класс также имеет размер 8, хотя он не пустой и является производным от базового класса размера 8. Таким образом, хранилище для derived::z перекрывает объект base: z хранится в заполнении base.

Это не происходит в других сценариях ios. Например, если я изменю intchar на struct вместо class, тогда derived как размер 12: нет перекрытия.

Есть ли какое-либо условие или черта, которую я могу проверить на базовый класс , который исключает перекрытие? В этом конкретном примере c работает std::is_aggregate, но я не знаю ни одной причины, по которой это должно быть так или не получится в другом примере.


1 Как ни странно, i cc здесь несовместим, сообщая о размере derived как 12, так что я предполагаю, что он не совместим с C ++ ABI с clang или g cc.

1 Ответ

2 голосов
/ 22 января 2020

Если может быть перекрытие, это должно произойти для вашего тестового примера только с одним char, чтобы вы могли написать черту типа, подобную этой:

template<class Base>
struct can_overlap {
    private:
        struct helper : Base {
            char a;
        };
    public:
    static constexpr bool value = sizeof(Base) == sizeof(helper);
};

template<class B>
static constexpr bool can_overlap_v = can_overlap<B>::value;

static_assert(can_overlap_v<intchar>);

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

...