C++중 dynamic 분석cast 와 staticcast 실례 문법 상세 설명
11430 단어 C++dynamic caststatic 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 대상 으로 전환 하도록 강요 하 는 데 사 용 됩 니 다.컴 파일 시 검 사 는 다 중 변환 이 아 닌 포인터 및 기타 로 전환 할 수 있 으 나 실행 시 유형 검 사 를 하지 않 아 전환 의 안전성 을 보장 합 니 다.그것 은 주로 다음 과 같은 몇 가지 용법 이 있다.
위험 이 비교적 낮은 용법:
void *
회전int *
,char *
회전void *
등;int *
회전double *
,Student *
회전int *
등 이다.서로 다른 유형의 데이터 저장 형식 이 다 르 고 길이 도 다 릅 니 다.A 유형의 포인터 로 B 형식의 데 이 터 를 가리 키 면 A 유형의 방식 으로 데 이 터 를 처리 합 니 다.읽 기 동작 이 라면 의미 없 는 값 을 얻 을 수 있 습 니 다.기록 작업 이 라면 B 형식의 데 이 터 를 파괴 할 수 있 습 니 다.다시 B 형식 으로 데 이 터 를 읽 을 때 의미 없 는 값 을 얻 을 수 있 습 니 다.
#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_cast2.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캐 스 트 내용 은 저희 의 이전 글 을 검색 하거나 아래 의 관련 글 을 계속 찾 아 보 세 요.앞으로 도 많은 응원 부 탁 드 리 겠 습 니 다!
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Visual Studio에서 파일 폴더 구분 (포함 경로 설정)Visual Studio에서 c, cpp, h, hpp 파일을 폴더로 나누고 싶었습니까? 어쩌면 대부분의 사람들이 있다고 생각합니다. 처음에 파일이 만들어지는 장소는 프로젝트 파일 등과 같은 장소에 있기 때문에 파일...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.