C++중 dynamic 분석cast 와 staticcast 실례 문법 상세 설명

1. static_cast
1.1 static_cast 문법

static_cast< new_type >(expression)
비고:newtype 은 대상 데이터 형식 이 고 expression 은 원본 데이터 형식 변수 나 표현 식 입 니 다.
C 스타일 쓰기:

double scores = 96.5;
int n = (int)scores;
C++새로운 스타일 의 작성 방법 은 다음 과 같 습 니 다.

double scores = 96.5;
int n = static_cast<int>(scores);
1.2 왜 static등급 을 낮추다
암시 적 유형 전환 은 안전 하고 명시 적 유형 전환 은 위험 하 다.C 언어 가 강제 유형 전환 의 문법 을 추가 하 는 이 유 는 위험 을 강조 하고 프로그래머 가 자신 이 무엇 을 하고 있 는 지 깨 닫 게 하기 위해 서 이다.
그러나 이런 위험 을 강조 하 는 방식 은 비교적 조방 하고 입도 가 비교적 크 며 어떤 위험 이 존재 하 는 지,위험 정도 가 어떤 지 밝 히 지 않 았 다.
잠재 적 인 위험 을 더욱 세분 화하 고 문제 의 트 레이스 를 더욱 편리 하 게 하 며 쓰기 형식 을 더욱 규범화 시 키 기 위해 C++는 유형 전환 을 분류 하고 네 개의 키 워드 를 추가 하여 지원 했다.이들 은 다음 과 같다.
키워드
설명 하 다.
static_cast
양성 전환 에 사용 하면 일반적으로 의외 의 발생 을 초래 하지 않 고 위험 이 매우 낮다.
const_cast
const 와 비 const,volatile 과 비 volatile 간 의 전환 에 사용 합 니 다.
reinterpret_cast
고도 로 위험한 전환 입 니 다.이러한 전환 은 바 이 너 리 에 대한 재해 석 일 뿐 기 존의 전환 규칙 을 통 해 데 이 터 를 조정 하지 않 지만 가장 유연 한 C+유형 전환 을 실현 할 수 있 습 니 다.
dynamic_cast
RTTI 의 도움 을 받 아 유형 안전 한 하향 전환(Downcasting)에 사용 합 니 다.
1.2 static_캐 스 트 의 역할
static_cast 는 전통 적 인 C 언어 에서 의 강제 전환 에 해당 하 며,이 연산 자 는 expression 을 new 로 변환 합 니 다.type 형식 은 non-const 대상 을 const 대상 으로 전환 하도록 강요 하 는 데 사 용 됩 니 다.컴 파일 시 검 사 는 다 중 변환 이 아 닌 포인터 및 기타 로 전환 할 수 있 으 나 실행 시 유형 검 사 를 하지 않 아 전환 의 안전성 을 보장 합 니 다.그것 은 주로 다음 과 같은 몇 가지 용법 이 있다.
위험 이 비교적 낮은 용법:
  • 기 존의 자동 유형 전환,예 를 들 어 short 전환 int,int 전환 double,const 전환 비 const,위로 전환 등;
  • void 지침 과 구체 적 인 유형 지침 간 의 전환,예 를 들 어void *회전int *,char *회전void *등;
  • 구조 함수 나 유형 변환 함수 의 클래스 와 다른 유형 간 의 전환 이 있 습 니 다.예 를 들 어 double 전 Complex(구조 함수 호출),Complex 전 double(유형 변환 함수 호출)등 이 있 습 니 다.
  • 주의해 야 할 것 은,staticcast 는 유형 간 의 전환 에 사용 할 수 없습니다.이러한 전환 은 모두 위험 하기 때 문 입 니 다.예 를 들 어:
  • 두 가지 구체 적 인 유형의 지침 간 의 전환,예 를 들 어int *회전double *,Student *회전int *등 이다.서로 다른 유형의 데이터 저장 형식 이 다 르 고 길이 도 다 릅 니 다.A 유형의 포인터 로 B 형식의 데 이 터 를 가리 키 면 A 유형의 방식 으로 데 이 터 를 처리 합 니 다.읽 기 동작 이 라면 의미 없 는 값 을 얻 을 수 있 습 니 다.기록 작업 이 라면 B 형식의 데 이 터 를 파괴 할 수 있 습 니 다.다시 B 형식 으로 데 이 터 를 읽 을 때 의미 없 는 값 을 얻 을 수 있 습 니 다.
  • int 와 포인터 사이 의 전환.구체 적 인 주 소 를 포인터 변수 에 할당 하 는 것 은 매우 위험 합 니 다.이 주소 의 메모리 가 할당 되 지 않 았 을 수도 있 고 읽 기와 쓰기 권한 이 없 을 수도 있 습 니 다.마침 사용 가능 한 메모리 가 오히려 작은 확률 의 사건 일 수도 있 습 니 다.
  • 1.3 static_cast 용법
    
    #include <iostream>
    #include <cstdlib>
    using namespace std;
    class Complex{
    public:
        Complex(double real = 0.0, double imag = 0.0): m_real(real), m_imag(imag){ }
    public:
        operator double() const { return m_real; }  //      
    private:
        double m_real;
        double m_imag;
    };
    int main(){
        //        
        int m = 100;
        Complex c(12.5, 23.8);
        long n = static_cast<long>(m);  //   ,      
        char ch = static_cast<char>(m);  //   ,       
        int *p1 = static_cast<int*>( malloc(10 * sizeof(int)) );  // void           
        void *p2 = static_cast<void*>(p1);  //       ,   void  
        double real= static_cast<double>(c);  //        
       
        //         
        float *p3 = static_cast<float*>(p1);  //                  
        p3 = static_cast<float*>(0X2DF9);  //            
        return 0;
    }
    2. dynamic_cast
    2.1 dynamic_cast 문법
    
    dynamic_cast <newType> (expression)
    new Type 과 expression 은 포인터 형식 이나 참조 형식 이 어야 합 니 다.다시 말 하면,dynamiccast 는 포인터 형식 과 인용 형식 만 바 꿀 수 있 고 다른 유형(int,double,배열,클래스,구조 체 등)은 안 됩 니 다.
    포인터 에 대해 변환 에 실패 하면 NULL 로 돌아 갑 니 다.인용 에 대해 서 는 변환 에 실패 하면std::bad_cast이상 을 던 집 니 다.
    2.2 dynamic_cast 용법
    dynamic_cast 는 클래스 의 계승 단계 간 에 유형 전환 을 하 는 데 사 용 됩 니 다.위로 전환(Upcasting)도 허용 하고 아래로 전환(Downcation)도 허용 합 니 다.위로 전환 하 는 것 은 무조건 적 이 고 어떠한 검 측 도 하지 않 기 때문에 모두 성공 할 수 있다.아래로 전환 하 는 전 제 는 반드시 안전 해 야 하 며 RTTI 를 통 해 검 사 를 해 야 하 며 모든 것 이 일부분 만 성공 할 수 있다.
    dynamic_cast 와 staticcast 는 상대 적 인,dynamiccast 는'동적 전환'이라는 뜻 으로 staticcast 는 정적 전환 이라는 뜻 이다.dynamic_cast 는 프로그램 이 실행 되 는 동안 RTTI 를 통 해 형식 변환 을 할 것 입 니 다.이 는 기본 클래스 에 가상 함 수 를 포함 해 야 합 니 다.static_cast 는 컴 파일 기간 에 형식 변환 을 완성 하면 오 류 를 더욱 신속하게 발견 할 수 있 습 니 다.
    2.3 dynamic_cast 실례
    2.3.1 상 향 전환(Upcasting)
    위로 전환 할 때 전환 해 야 할 두 가지 유형 사이 에 계승 관계 가 존재 하고 기 류 는 가상 함수(이런 정 보 는 컴 파일 기간 에 확정 할 수 있다)를 포함 하면 반드시 전환 에 성공 할 수 있다.상 향 전환 은 언제나 안전 하기 때문에 dynamiccast 는 실행 중인 동안 의 검 사 를 하지 않 습 니 다.이때 의 dynamiccast 와 static캐 스 트 는 다 를 게 없어.
    '위로 전환 할 때 운행 기 검 사 를 실행 하지 않 습 니 다'는 효율 을 높 였 지만 안전 위험 도 남 겼 습 니 다.아래 코드 를 보십시오.
    
    #include <iostream>
    #include <iomanip>
    using namespace std;
    class Base{
    public:
        Base(int a = 0): m_a(a){ }
        int get_a() const{ return m_a; }
        virtual void func() const { }
    protected:
        int m_a;
    };
    
    class Derived: public Base{
    public:
        Derived(int a = 0, int b = 0): Base(a), m_b(b){ }
        int get_b() const { return m_b; }
    private:
        int m_b;
    };
    
    int main(){
        //  ①
        Derived *pd1 = new Derived(35, 78);
        Base *pb1 = dynamic_cast<Derived*>(pd1);
        cout<<"pd1 = "<<pd1<<", pb1 = "<<pb1<<endl;
        cout<<pb1->get_a()<<endl;
        pb1->func();
        //  ②
        int n = 100;
        Derived *pd2 = reinterpret_cast<Derived*>(&n);
        Base *pb2 = dynamic_cast<Base*>(pd2);
        cout<<"pd2 = "<<pd2<<", pb2 = "<<pb2<<endl;
        cout<<pb2->get_a()<<endl;  //       
        pb2->func();  //    
        return 0;
    }
    실행 결 과 는 다음 과 같다.

    pd1 과 pb1 의 주소 가 같 고 pb1 은 Base 류 를 정상적으로 호출 할 수 있 는 방법 을 볼 수 있 습 니 다.
    상황 ②
    pd 2 는 정형 변수 n 을 가리 키 며,Derived 클래스 의 대상 을 가리 키 지 않 고,dynamic 를 사용 합 니 다.cast 가 유형 전환 을 할 때 도 이 점 을 검사 하지 않 았 습 니 다(위로 전환 하 는 것 은 항상 안전 하기 때문에 다이나믹캐 스 트 는 런 타임 검 사 를 하지 않 습 니 다)
    pd 의 값 을 pb 에 직접 부 여 했 습 니 다.pb 가 가리 키 는 것 은 하나의 대상 이 아니 기 때문에get_a()m 를 얻 을 수 없습니다.a 의 값(실제로 얻 은 것 은 쓰레기 값),pb2->func()도 func()함수 의 정확 한 주 소 를 얻 을 수 없습니다.
    실행 결 과 는 다음 과 같다.


    쉽게 말 하면 위로 전환 하 는 것 은 검사 하지 않 는 것 이기 때문에 여러분 은 자신 이 무엇 을 하고 있 는 지 알 아야 합 니 다.함부로 전환 해 서 는 안 됩 니 다.
    2.3.2 하향 전환(다운 캐 스 팅)
    아래로 전환 하 는 것 은 위험 합 니 다.dynamiccast 는 RTTI 정 보 를 통 해 검 사 를 하고 안전 한 것 을 확인 해 야 전환 에 성공 할 수 있 으 며 그렇지 않 으 면 전환 에 실패 합 니 다.
    다음은 예 를 보 겠 습 니 다.
    
    #include <iostream>
    using namespace std;
    class A{
    public:
        virtual void func() const { cout<<"Class A"<<endl; }
    private:
        int m_a;
    };
    class B: public A{
    public:
        virtual void func() const { cout<<"Class B"<<endl; }
    private:
        int m_b;
    };
    class C: public B{
    public:
        virtual void func() const { cout<<"Class C"<<endl; }
    private:
        int m_c;
    };
    class D: public C{
    public:
        virtual void func() const { cout<<"Class D"<<endl; }
    private:
        int m_d;
    };
    int main(){
        A *pa = new A();
        B *pb;
        C *pc;
       
        //  ①
        pb = dynamic_cast<B*>(pa);  //      
        if(pb == NULL){
            cout<<"Downcasting failed: A* to B*"<<endl;
        }else{
            cout<<"Downcasting successfully: A* to B*"<<endl;
            pb -> func();
        }
        pc = dynamic_cast<C*>(pa);  //      
        if(pc == NULL){
            cout<<"Downcasting failed: A* to C*"<<endl;
        }else{
            cout<<"Downcasting successfully: A* to C*"<<endl;
            pc -> func();
        }
       
        cout<<"-------------------------"<<endl;
       
        //  ②
        pa = new D();  //         
        pb = dynamic_cast<B*>(pa);  //      
        if(pb == NULL){
            cout<<"Downcasting failed: A* to B*"<<endl;
        }else{
            cout<<"Downcasting successfully: A* to B*"<<endl;
            pb -> func();
        }
        pc = dynamic_cast<C*>(pa);  //      
        if(pc == NULL){
            cout<<"Downcasting failed: A* to C*"<<endl;
        }else{
            cout<<"Downcasting successfully: A* to C*"<<endl;
            pc -> func();
        }
       
        return 0;
    }
    실행 결과

    앞의 두 번 의 전환 은 실 패 했 지만,뒤의 두 번 의 전환 은 성공 했다 는 것 을 알 수 있다.
    이 코드 의 계승 순 서 는 A-->B-->C-->D 입 니 다.pa 는A*유형의 지침 으로 pa 가 A 유형의 대상 을 가리 킬 때 아래로 전환 하 는 데 실 패 했 고 pa 는B*또는C*유형 으로 전환 할 수 없습니다.pa 가 D 유형의 대상 을 가리 킬 때 아래로 전환 에 성공 하면 pa 는B*또는C*유형 으로 전환 할 수 있 습 니 다.똑 같이 아래로 전환 하 는데 왜 pa 가 가리 키 는 대상 이 다 르 고 전환 의 결 과 는 크게 다 릅 니까?
    각 종 류 는 메모리 에 하나의 유형 정 보 를 저장 하기 때문에 컴 파일 러 는 계승 관계 가 존재 하 는 유형의 정 보 를 포인터 로 연결 하여 하나의 계승 체인(Inheritance Chain)을 형성한다.즉,다음 그림 과 같다.

    dynamic 사용 시캐 스 트 가 포인터 에 대해 유형 전환 을 할 때 프로그램 은 먼저 이 포인터 가 가리 키 는 대상 을 찾 은 다음 에 대상 에 따라 현재 클래스(포인터 가 가리 키 는 대상 이 속 한 클래스)의 유형 정 보 를 찾 고 이 노드 부터 계승 체인 을 따라 위로 옮 겨 다 닌 다.전환 할 목표 유형 을 찾 으 면 이런 전환 이 안전 하 다 는 것 을 설명 하고 전환 에 성공 할 수 있다.전환 할 목표 유형 을 찾 지 못 하면 이런 전환 에 비교적 큰 위험 이 존재 하고 전환 할 수 없다 는 것 을 의미한다.
    그래서 두 번 째 방식 에서 파 는 실제 적 으로 D 를 가리 키 기 시 작 했 고 프로그램 은 D 를 따라 위로 찾기 시 작 했 고 B 와 C 를 찾 았 기 때문에 안전 하 다 고 인 정 했 기 때문에 전환 에 성공 했다.
    총괄 적 으로 말 하면,dynamic캐 스 트 는 프로그램 이 실행 되 는 과정 에서 계승 체인 을 옮 겨 다 닙 니 다.만약 에 도중에 전환 할 목표 유형 을 만 났 다 면 성공 적 으로 전환 할 수 있 습 니 다.만약 에 계승 체인 의 정점(최상 위 클래스)까지 전환 할 목표 유형 을 만 나 지 못 했다 면 전환 에 실 패 했 습 니 다.같은 포인터(예 를 들 어 pa)가 가리 키 는 대상 이 다 르 면 계승 체인 을 옮 겨 다 니 는 출발점 이 다 르 고 도중에 일치 할 수 있 는 유형 도 다 르 기 때문에 같은 유형 전환 은 서로 다른 결 과 를 얻 었 다.
    3.링크 참조
    http://c.biancheng.net/cpp/biancheng/view/3297.html
    https://blog.csdn.net/u014624623/article/details/79837849
    https://www.cnblogs.com/wanghongyang/[본문 블 로그]
    이 편 은 C++중 dynamic 에 대한 분석 입 니 다.cast 와 staticcast 인 스 턴 스 가 보 여 준 글 은 여기까지 입 니 다.더 많은 관련 C++중 다이나믹cast 와 static캐 스 트 내용 은 저희 의 이전 글 을 검색 하거나 아래 의 관련 글 을 계속 찾 아 보 세 요.앞으로 도 많은 응원 부 탁 드 리 겠 습 니 다!

    좋은 웹페이지 즐겨찾기