указатели — некоторые загадки о подобъекте в стандарте C ++

Стандарт C ++ определяет понятие «динамический тип» glvalue следующим образом:

динамический тип

<glvalue> тип самого производного объекта (1.8), на который ссылается glvalue, обозначенный выражением glvalue [Пример: если указатель (8.3.1) p со статическим типом «указатель на класс B» указывает на объект класса D, полученный из B (раздел 10), динамический тип выражения * p равен «D». Ссылки (8.3.2) обрабатываются аналогично. — конец примера]

Как это определение интерпретируется, если то, на что ссылается glvalue, не является самым производным объектом? Означает ли это «тип самого производного объекта который содержит объект на что ссылается glvalue, обозначаемый выражением glvalue «?

Еще одна загадка о 4-м абзаце в 5.7 стандарта C ++:

… Если операнд-указатель указывает на элемент объекта массива, …

Я хочу спросить, выполняется ли это условие, если указатель операнда указывает на подобъект элемент объекта массива. Например, если он не выполняется, то поведение в следующем коде не определено, верно?

D d[10];
B *p = d; //B is a base class of D
p += 2;   //undefined behavior?

1

Решение

Формулировка понятна. Предполагается, что наиболее производный объект представляет собой законченный объект, элемент данных или элемент массива, т.е. он не является подобъектом базового класса.

WG21 / N4527

1.8 Объектная модель C ++ [intro.object]

2 объекта могут содержать другие объекты, называемые субобъекты. субобъект может быть подобъект участника (9.2), а подобъект базового класса (Пункт 10) или элемент массива. Объект, который не является подобъектом любого другого объекта, называется законченным объектом.

3 Для каждого объекта xесть некоторый объект под названием завершить объект из xопределяется следующим образом:

(3.1) — Если x является законченным объектом, то x является полным объектом x,

(3.2) — В противном случае, полный объект x является полным объектом (уникального) объекта, который содержит x,

4 Если полный объект, элемент данных (9.2) или элемент массива относятся к типу класса, его тип считается самый производный класс, отличить его от типа класса любого подобъекта базового класса; объект самого производного типа класса или не-классового типа называется самый производный объект.

D d[10];
B *p = d; //B is a base class of D
p += 2;   //undefined behavior?

Это имеет неопределенное поведение, несомненно. Нет никаких дополнительных правил о производных классах. И так как каждый операнд выражения p += 2 is prvalue, динамические типы glvalues ​​не рассматриваются.

Изменить: Обратите внимание, что динамические типы значений совпадают с их статическими типами.

1

Другие решения

«Вопрос» может быть лучше, чем слово «загадка» здесь.

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

Особенно, p укажет 2 B размеры от начала массива, а не 2 D размеры. Опять же, это совершенно четко определено. Однако доступ к этой памяти может быть недостаточно определен.

0

Как это определение интерпретируется, если то, на что ссылается glvalue, не является самым производным объектом?

Если glvalue относится к действительному объекту, это ВСЕГДА самый производный объект, который был построенный, не обязательно самый производный тип базового типа.

Пример:

class Base {};
class Derived1 : public Base {};
class Derived2 : public Derived1 {};

Base* ptr = new Derived1;

*ptr относится к Derived1не Derived2 поскольку объект, который был построен, имеет тип Derived1,

D d[10];
B *p = d; //B is a base class of D
p += 2;   //undefined behavior?

Да, это неопределенное поведение.

0
По вопросам рекламы [email protected]