6.10.5 dynamic_cast 와 RTTI

phoenixKim·2021년 8월 21일
0

fundamental c++

목록 보기
2/14

고찰

: 부모에서 자식으로의 형변환은 되지 않지만, 전혀 연관이 없는 클래스 간의
형변환이 가능한 것은 의문이다.(static_cast, reinterpret_cast에서 )
허용하는 이유는 그렇게 사용해야만 하는 경우가 있기 때문이다. 알아보자!

소스코드


-> 추상자료형을 넣는다면 문제가 되지 않지만, 부모를 넣는다면 미정 동작한다.
원래는 CChild객체에 대해서만 형변환을 허용한다면 더욱 안전할지 않을까란 생각을 하게된다.
그런 생각에서 나온 개념이 dynamic_cast이다.

RTTI

런타임 타입 정보를 사용하여 타입변환을 하는 연산자이다.
실행시간에 타입 정보를 검사하여 제대로 된 형변환만을 허용하기 때문에,
안전성 면에서는 뛰어나지만, 성능을 좋지 않다.

  • 설정을 해줘야 한다.
  • 가상함수를 하나라도 선언해서 가상함수 포인터를 만들어야 한다.

~~ 아 어렵다...~~

dynamic_cast

dynamic_cast를 이용하면 가상상속에서의 형변환을 어느 정도 해결할 수 있다.

  • 강제형변환이나 static_cast의 경우, 일반 상속이면 타입 변환이 허용되고, 가상상속에서는 타입 변환이 거부된다. 하지만 dynamic_cast의 경우에는 실제 타입에 따라서 안전하게 타입 변환을 해준다는 점에서 의미가 있다.

  • 형변환이 실패할 경우, 포인터형이었다면 nullPtr을 반환하고,
    레퍼런스 형이었다면 예외처리된다.

  • 하나 이상의 virtual이 존재해야 한다.

dynamic_cast가 static_cast이나 강제형변환보다 안전한 이유는..
static_cast나 강제 형변환으로 부모를 자식으로 변환할 경우,
성공은 하지만,,, 자식 멤버의 값은 어떻게 될지 미정이다.
but, dynamic_cast의 경우, 실패하면 null이나 예외처리를 하므로
비교적 안전하다.

관련 코드

포인터형 변환


#include <iostream>
using namespace std;

class CparentA
{
public : 
	virtual ~CparentA() {}
};

class CparentB
{
public:
	virtual ~CparentB() {}
};

class child : public CparentA, public CparentB
{
public : 
	int val;
};

int main()
{	
	{
		child c;
		CparentA *pA = dynamic_cast<CparentA *>(&c);
		CparentB *pB = dynamic_cast<CparentB *>(&c);
	}
	{
		CparentA a;
		child *pc1 = dynamic_cast<child *>(&a);
		if (pc1 == nullptr)
			cout << "pc1은 nullptr입니다." << endl;
		CparentB b;
		child *pc2 = dynamic_cast<child *>(&b);
		if (pc2 == nullptr)
			cout << "pc2은 nullptr입니다." << endl;

		child *pc3 = static_cast<child *>(&a);
		cout << "pc3의 멤버 값은 "<< pc3->val << endl;

		child *pc4 = static_cast<child *>(&b);
		cout << "pc4의 멤버 값은 " << pc4->val << endl;


	}
}

참조형은 예외처리한다.

dynamic_cast 활용하기

6-78 위험한 타입 변환 허용

: static_cast 사용

6-83 dynamic_cast를 이용한 형변환


-> 예외처리를 통해 안전한 형변환을 확인할 수 있다.

소스코드


#include <iostream>
using namespace std;

class parent
{
public : 
	char mValue;
	virtual ~parent() {}
};

class child : public parent
{
public:
	child()
	{
		mValue = 1;
		mChildValue = 2;
	}
	int mChildValue;
};

int GetValue(parent * pParent)
{
	if (pParent->mValue == 1)
	{
		child *pC = dynamic_cast<child*>(pParent);

		if (pC != nullptr)
		{
			return pC->mChildValue;
		}
		else
		{
			return 0;
		}
	}
	return 0;
}

int main()
{	
	child c;
	cout << (GetValue(&c)) << endl;
	
	parent p;
	p.mValue = 1;
	cout << (GetValue(&p)) << endl;
}
profile
🔥🔥🔥

0개의 댓글

관련 채용 정보