Namespaces
Variants

dynamic_cast conversion

From cppreference.net
C++ language
General topics
Flow control
Conditional execution statements
Iteration statements (loops)
Jump statements
Functions
Function declaration
Lambda function expression
inline specifier
Dynamic exception specifications ( until C++17* )
noexcept specifier (C++11)
Exceptions
Namespaces
Types
Specifiers
constexpr (C++11)
consteval (C++20)
constinit (C++20)
Storage duration specifiers
Initialization
Expressions
Alternative representations
Literals
Boolean - Integer - Floating-point
Character - String - nullptr (C++11)
User-defined (C++11)
Utilities
Attributes (C++11)
Types
typedef declaration
Type alias declaration (C++11)
Casts
Memory allocation
Classes
Class-specific function properties
Special member functions
Templates
Miscellaneous

클래스의 상속 계층 구조를 따라 위, 아래, 옆으로 안전하게 포인터와 참조를 변환합니다.

목차

구문

dynamic_cast< target-type >( expression )
target-type - 완전한 클래스 타입에 대한 포인터, 완전한 클래스 타입에 대한 참조, 또는 (선택적으로 cv-qualified) void 에 대한 포인터
expression - lvalue (C++11 이전) glvalue (C++11 이후) target-type 이 참조인 경우 완전한 클래스 타입의 lvalue, target-type 이 포인터인 경우 완전한 클래스 타입에 대한 포인터의 prvalue

설명

설명의 편의를 위해, " expression 또는 결과가 T 에 대한 참조이다"는 "이것이 T 타입의 glvalue이다"를 의미합니다 , 이는 decltype 의 관례를 따릅니다 (since C++11) .

다음 변환만 dynamic_cast 로 수행할 수 있으며, 이러한 변환이 constness 제거 (또는 volatility 제거)를 유발하는 경우는 예외입니다.

1) expression 의 타입이 정확히 target-type 이거나 target-type 의 더 적은 cv-한정 버전인 경우, 결과는 expression 의 값을 target-type 타입으로 가집니다. 다른 말로, dynamic_cast constness를 추가하는 데 사용될 수 있습니다. 암시적 변환과 static_cast 도 이 변환을 수행할 수 있습니다.
2) 만약 target-type 이 "(cv 한정자가 있을 수 있는) Base 에 대한 포인터"이고 expression 의 타입이 "(cv 한정자가 있을 수 있는) Derived 에 대한 포인터"이며 Base Derived 의 기본 클래스인 경우, 결과는
  • expression 이 null 포인터 값인 경우 null 포인터 값, 또는
  • 그렇지 않은 경우 expression 이 가리키는 Derived 객체의 고유한 Base 서브객체 를 가리키는 포인터입니다. 즉, dynamic_cast 는 파생 클래스에서 기본 클래스로 포인터를 업캐스트 하는 데 사용할 수 있습니다. 암시적 변환과 static_cast 도 이 변환을 수행할 수 있습니다.
3) 만약 target-type 이 "(cv 한정자가 있을 수 있는) Base 에 대한 참조"이고 expression 의 타입이 "(cv 한정자가 있을 수 있는) Derived "이며 Base Derived 의 기본 클래스인 경우, 결과는 expression 이 참조하는 Derived 객체 내 유일한 Base 서브객체입니다. 즉, dynamic_cast 는 파생 클래스에서 기본 클래스로 참조를 업캐스트 하는 데 사용될 수 있습니다. 암시적 변환과 static_cast 도 이 변환을 수행할 수 있습니다.
4) 만약 expression 다형성 타입 의 널 포인터 값이라면, 결과는 target-type 의 널 포인터 값입니다.
5) 그렇지 않은 경우, expression 은 해당 수명 내에 있거나 생성 또는 소멸 기간 중에 있는 다형성 타입 객체에 대한 포인터나 참조여야 하며, 해당 타입은 expression 의 타입과 유사 해야 합니다(그렇지 않으면 동작은 정의되지 않음).
a) 만약 expression 이 (cv-qualified일 수 있는) void 에 대한 포인터라면, 결과는 expression 이 가리키는 가장 파생된 객체 에 대한 포인터입니다.
b) 그렇지 않은 경우, 런타임 검사가 적용되어 expression 이 가리키거나 참조하는 객체가 target-type 이 가리키거나 참조하는 Target 타입으로 변환될 수 있는지 확인합니다:
i) expression 이 가리키거나 참조하는 가장 파생된 객체에서, expression Target 객체의 public 기반 클래스 하위 객체를 가리키거나 참조하고, expression 이 가리키거나 참조하는 하위 객체로부터 파생된 Target 타입의 객체가 단 하나만 존재하는 경우, 결과는 해당 Target 객체를 가리키거나 참조합니다. 즉, dynamic_cast 는 포인터/참조를 다운캐스트 하는 데 사용될 수 있으며, 이는 기반 클래스에서 파생 클래스로의 변환을 의미합니다.
ii) 그렇지 않고 expression 이 최종 파생 객체의 public 기반 클래스 하위 객체를 가리키거나 참조하고, 최종 파생 객체의 타입이 Target 타입의 명확하고 public인 기반 클래스를 갖는 경우, 결과는 최종 파생 객체의 Target 하위 객체를 가리키거나 참조합니다. 다른 말로, dynamic_cast 는 동일한 기반에서 파생된 두 타입 간에 포인터/참조의 교차 캐스팅 (또는 사이드 캐스팅)에 사용될 수 있습니다.
iii) 그렇지 않으면, 런타임 검사가 실패합니다.
  • 만약 target-type 이 포인터 타입인 경우, 결과는 target-type 의 널 포인터 값입니다.
  • 만약 target-type 이 참조 타입인 경우, std::bad_cast 타입의 핸들러 와 일치하는 타입의 예외가 발생합니다.

생성자나 소멸자 내에서(직접적 또는 간접적으로) dynamic_cast 가 사용되고, expression 이 현재 생성/소멸 중인 객체를 참조할 때, 해당 객체는 가장 파생된 객체로 간주됩니다. 만약 target-type 이 생성자/소멸자 자신의 클래스나 그 기반 클래스 중 하나에 대한 포인터나 참조가 아닌 경우, 그 동작은 정의되지 않습니다.

다른 형변환 표현식과 유사하게, 결과는 다음과 같습니다:

  • target-type 이 참조 타입인 경우 lvalue
  • target-type 이 포인터 타입인 경우 rvalue
(C++11 이전)
  • target-type 이 lvalue 참조 타입인 경우 lvalue ( expression 은 lvalue여야 함)
  • target-type 이 rvalue 참조 타입인 경우 xvalue ( expression 은 lvalue 또는 rvalue일 수 있음 (C++17 이전) 은 glvalue여야 함 (prvalue는 materialized 됨) (C++17 이후) 완전한 클래스 타입)
  • target-type 이 포인터 타입인 경우 prvalue
(C++11 이후)

참고 사항

다운캐스트는 static_cast 를 사용해서도 수행할 수 있으며, 이는 런타임 검사의 비용을 피할 수 있지만, expression 이 가리키는 객체가 반드시 Derived 라는 것을 프로그램이 (다른 논리를 통해) 보장할 수 있는 경우에만 안전합니다.

일부 형태의 dynamic_cast 런타임 타입 식별 (RTTI), 즉 컴파일된 프로그램 내의 각 다형성 클래스에 대한 정보에 의존합니다. 컴파일러는 일반적으로 이 정보의 포함을 비활성화하는 옵션을 제공합니다.

키워드

dynamic_cast

예제

#include <iostream>
struct V
{
    virtual void f() {} // 런타임 검사 dynamic_cast를 사용하려면 반드시 다형성이 있어야 함
};
struct A : virtual V {};
struct B : virtual V
{
    B(V* v, A* a)
    {
        // 생성 중 캐스트 (아래 D의 생성자 호출 참조)
        dynamic_cast<B*>(v); // 올바르게 정의됨: v는 V* 타입, V는 B의 기반 클래스, 결과는 B*
        dynamic_cast<B*>(a); // 정의되지 않은 동작: a는 A* 타입, A는 B의 기반 클래스가 아님
    }
};
struct D : A, B
{
    D() : B(static_cast<A*>(this), this) {}
};
struct Base
{
    virtual ~Base() {}
};
struct Derived : Base
{
    virtual void name() {}
};
int main()
{
    D d; // 가장 파생된 객체
    A& a = d; // 업캐스트, dynamic_cast를 사용할 수 있지만 불필요함
    [[maybe_unused]]
    D& new_d = dynamic_cast<D&>(a); // 다운캐스트
    [[maybe_unused]]
    B& new_b = dynamic_cast<B&>(a); // 사이드캐스트
    Base* b1 = new Base;
    if (Derived* d = dynamic_cast<Derived*>(b1); d != nullptr)
    {
        std::cout << "downcast from b1 to d successful\n";
        d->name(); // 안전하게 호출 가능
    }
    Base* b2 = new Derived;
    if (Derived* d = dynamic_cast<Derived*>(b2); d != nullptr)
    {
        std::cout << "downcast from b2 to d successful\n";
        d->name(); // 안전하게 호출 가능
    }
    delete b1;
    delete b2;
}

출력:

downcast from b2 to d successful

결함 보고서

다음의 동작 변경 결함 보고서들은 이전에 발표된 C++ 표준에 소급 적용되었습니다.

DR 적용 대상 게시된 동작 올바른 동작
CWG 1269 C++11 대상-유형이 rvalue 참조 유형일 때 xvalue
expression 에 대해 런타임 검사가 수행되지 않았음
수행됨
CWG 2861 C++98 expression 이 유형에 접근 불가능한 객체를 가리키거나 참조할 수 있었음 이 경우 동작이 정의되지 않음

참조문헌

  • C++23 표준 (ISO/IEC 14882:2024):
  • 7.6.1.7 Dynamic cast [expr.dynamic.cast]
  • C++20 표준(ISO/IEC 14882:2020):
  • 7.6.1.6 Dynamic cast [expr.dynamic.cast]
  • C++17 표준 (ISO/IEC 14882:2017):
  • 8.2.7 Dynamic cast [expr.dynamic.cast]
  • C++14 표준(ISO/IEC 14882:2014):
  • 5.2.7 Dynamic cast [expr.dynamic.cast]
  • C++11 표준(ISO/IEC 14882:2011):
  • 5.2.7 Dynamic cast [expr.dynamic.cast]
  • C++98 표준(ISO/IEC 14882:1998):
  • 5.2.7 Dynamic cast [expr.dynamic.cast]
  • C++03 표준(ISO/IEC 14882:2003):
  • 5.2.7 Dynamic cast [expr.dynamic.cast]

참고 항목