8 Expressions [expr]

8.2 Postfix expressions [expr.post]

8.2.7 Dynamic cast [expr.dynamic.cast]

Результат выражения dynamic_­cast<T>(v) - это результат преобразования выражения v в тип T. T должен быть указателем или ссылкой на полный тип класса, или «указателем на cv void». dynamic_­cast Оператор не должен cast away constness.

Если T это тип указателя, v должно быть prvalue указателя на полный тип класса, а результатом будет prvalue типа T. Если T - ссылочный тип lvalue, v должен быть lvalue полного типа класса, а результатом будет lvalue типа, на который ссылается T. Если T это ссылочный тип rvalue, v должно быть glvalue, имеющее полный тип класса, а результатом будет значение x того типа, на который ссылается T.

Если тип v такой же Tили такой же, T за исключением того, что тип объекта класса в T более cv-квалифицирован, чем тип объекта класса в v, результат будет v (при необходимости преобразован).

Если значение v является значением нулевого указателя в случае указателя, результатом является значение нулевого указателя типа T.

Если T это «указатель на cv1 B» и v имеет тип «указатель на cv2 D», то B есть базовый класс D, результатом является указатель на уникальный B подобъект D объекта, на который указывает v. Точно так же, если T это «ссылка на cv1 B» и v имеет cv2 D такой тип , который B является базовым классом D, результатом является уникальный B подобъект D объекта, на который ссылается v.69 Как в случае указателя, так и в случае ссылки, программа плохо сформирована, если cv2 имеет более высокую квалификацию cv, чем недоступный или неоднозначный базовый класс cv1 или если он B является D. [Example:

struct B { };
struct D : B { };
void foo(D* dp) {
  B*  bp = dynamic_cast<B*>(dp);    // equivalent to B* bp = dp;
}

end example]

В противном случае v должен быть указателем или значением glvalue polymorphic type.

Если T это «указатель на cv void», то результатом является указатель на самый производный объект, на который указывает v. В противном случае применяется проверка времени выполнения, чтобы увидеть, может ли объект, на который указывает или на который ссылается, v быть преобразован в тип, на который указывает или на который ссылается T.

Если C это тип класса, на который T указывает или ссылается, проверка времени выполнения логически выполняется следующим образом:

  • Если в наиболее производном объекте, на который указывает (упоминается) v, v указывает (ссылается) на public подобъект базового класса C объекта, и если только один объект типа C является производным от подобъекта, на который указывает (ссылается) v результирующие точки (ссылается ) к этому C объекту.

  • В противном случае, если v указывает (ссылается) на public подобъект базового класса самого производного объекта, а тип самого производного объекта имеет базовый класс типа C, который является однозначным, и publicрезультат указывает (ссылается) на C подобъект самый производный объект.

  • В противном случае проверка времени выполнения fails.

Значение неудачного приведения к типу указателя - это значение нулевого указателя требуемого типа результата. Неудачное приведение к типу ссылки throws an exception на тип, который соответствует handler типу std​::​bad_­cast.

[Example:

class A { virtual void f(); };
class B { virtual void g(); };
class D : public virtual A, private B { };
void g() {
  D   d;
  B*  bp = (B*)&d;                  // cast needed to break protection
  A*  ap = &d;                      // public derivation, no cast needed
  D&  dr = dynamic_cast<D&>(*bp);   // fails
  ap = dynamic_cast<A*>(bp);        // fails
  bp = dynamic_cast<B*>(ap);        // fails
  ap = dynamic_cast<A*>(&d);        // succeeds
  bp = dynamic_cast<B*>(&d);        // ill-formed (not a runtime check)
}

class E : public D, public B { };
class F : public E, public D { };
void h() {
  F   f;
  A*  ap  = &f;                     // succeeds: finds unique A
  D*  dp  = dynamic_cast<D*>(ap);   // fails: yields null; f has two D subobjects
  E*  ep  = (E*)ap;                 // ill-formed: cast from virtual base
  E*  ep1 = dynamic_cast<E*>(ap);   // succeeds
}

end example] [ Note: [class.cdtor] описывает поведение, dynamic_­cast применяемое к строящемуся или разрушающемуся объекту. ]end note

Указанный most derived object или упомянутый by v может содержать другие B объекты в качестве базовых классов, но они игнорируются.