BE/C++

[C++] dynamic_cast (타입 캐스트 연산자)

콩다영 2023. 9. 15.
728x90

C++ 타입 캐스트 연산자 _ dynamic_cast

 

 

 

C++의 4가지 캐스트 연산자 중에서 

다운캐스팅을 하기 위한 연산자 "dynamic_cast"에 대해 정리해 보자!

 

 

우선, C++에서 캐스팅이란  타입을 변환하는 것을 말한다. (=형변환)

 

▲ 업 캐스팅 : 자식 클래스 객체가 부모 클래스로 형변환을 하는 것

▼ 다운 캐스팅 : 업캐스팅 된 것을 다시 되돌리는 것

 

 

 

dynamic_cast는 부모 클래스 포인터에서 자식 클래스 포인터로 다운 캐스팅할 때 사용한다.

( 부모 클래스 포인터가 무엇을 가리키고 있는지에 따라서 결과가 달라질 수 있음을 주의하며 사용하기 !! )

 

 

▶ 사용법

: dynamic_cast <type-id> ( expression )

: dynamic_cast <변환형> (변환하려는 대상)

   ※ type-id  : 완전한 클래스의 포인터 또는 참조 이거나 void*이어야 된다.

 

 

▶ 제약사항

- 상속 관계에서만 사용이 가능하다.

- 하나 이상의 가상(virtual) 함수가 존재해야 한다. 

- 포인터나 참조 형을 캐스팅할 때만 쓸 수 있다. 

- 부모 자식 간 다운캐스팅할 때 무조건적으로 변환을 허용하지 않고 런타임 할 때 안전한지 판단하여 결과를 허용한다.

   -> 형변환 실패 시, 포인터는 nullptr를 반환하고 래퍼런스에 대해서는 std::bad_cast 예외를 발생시킨다.

   -> 런타임 때 안전한지 확인하기 때문에 런타임 비용이 높은 캐스트이다.

  -> static_cast와 동일하게 작동하나 dynamic_cast만 런타임 때 형타입 확인을 하기에 안전성에서는 dynamic_cast가 더 안전한 캐스트이다. 하지만 dynamic_cast는 컴파일 중에 RTTI(실시간 타입정보, Real-Time Type Information)를 켜야 하기 때문에 성능 쪽에서는 좀 느리다고는 한다고 한다..!! RTTI를 안 켜고 실행하면 static_cast와 dynamic_cast는 동일하게 작동된다.

 

 

 

 

[ dynamic_cast 사용 예제]

class Person {
public:
	virtual void intro() {
		cout << "사람입니다." << endl;
	}
};

class Student : public Person {
	string name;

public:
	Student(string name) {
		this->name = name;
	}
	void intro() {
		cout << name << "학생입니다." << endl;
	}

	void learn() {
		cout << "배웁니다." << endl;
	}
};

class Teacher : public Person {
	string name;

public:
	Teacher(string name) {
		this->name = name;
	}
	void intro() {
		cout << name << "선생입니다." << endl;
	}

	void teach() {
		cout << "가르칩니다." << endl;
	}
};

int main() {
	Person* pList[3];
	string names[3];

	cout << "3명의 이름을 입력해주세요. (선생님, 학생, 학생)" << endl;
	cin >> names[0] >> names[1] >> names[2];

	/* names[] 배열 이용하여 각 class 생성 */
	Teacher t = Teacher(names[0]);
	Student s1 = Student(names[1]);
	Student s2 = Student(names[2]);

	/* pList에 할당하는 코드 추가 */
	pList[0] = &t;
	pList[1] = &s1;
	pList[2] = &s2;

	for (auto p : pList) {
		p->intro();
	}

	/* 각 class의 고유 함수 실행 (teach(), learn(), learn())*/
	for (Person* person : pList) {
		Teacher* pt = dynamic_cast<Teacher*>(person);
		if (pt) {
			pt->teach();
		}
		else {
			Student* ps = dynamic_cast<Student*>(person);
			if (ps) {
				ps->learn();
			}
		}
	}
}

위에 예제에서는

Person(부모) <-> Teacher(자식), Student(자식)   이렇게 부모자식 간 형변환을 사용하였다.

 

 

 

 

 

728x90
반응형

댓글