CPP_어소_83_다형성

CJB_ny·2022년 7월 28일
0

CPP_AROTHO

목록 보기
82/83
post-thumbnail

CPP 에서의 다형성을 어떻게 이해를 하냐?

이것을 이해를 하기 위해서는

"상속 AND 포인터"를 알아볼 필요가 있다.

1번은 문제가 됨.

2번은 문제가 안됨.

기본적으로 파생클래스는 기반클래스의 정보를 알지만

기반클래스는 파생클래스의 정보를 모르기때문에

< 기반클래스 "변수명" = 파생클래스 > 로 형식 변환이 안된다.

포인터와 메모리를 같이 생각 ❗

메모리가 이렇게 잡혀있다.

먼저 부모부터 잡혀있음. 그다음에 자식.

Parent paremt;
Child child;

Parent* p1 = &child; // 1번
Child* c1 = &parent // 2번

1번의 경우에는 문제가 없음. (자식 -> 부모 형식변환)

2번의 경우 문제가 발생 (부모 -> 자식으로 형식 변환)

자식포인터로 부모 클래스를 가르키면 안된다 ❗

이렇게 자식이 존나 많고, 그 자식 객체의 사이즈는 다 다를것인데

Parent 포인터로 다 가르킬 수 있다. => 맨 앞에 Parent 클래스가 제일 앞에 있기 때문.

Parent* parent;

이녀석은 어떤 녀석의 (누구든지간에) 의 주소에 가면은 실제객체가 Parent가 아니라

누구든지 될 수 있다. 어떤 객체든지 될 수 있다.

타입은 Parent* 이고.

parent->

이렇게 가보면 아무나 (자식한정에서) 다 올 수 있다.

상황에 따라 주소를 바꾸면 다른 애들도 올 수 있다.

파생될 수 있는 모든 녀석들 중에 하나이다.

다형성

근데 이러한 사실만으로는 cpp의 다형성을 설명하기에 50% 모자르다.

Parent* parent = &child;

이런 포인터의 특성에 착안을 하였을 때, 문제가 생긴다.

이 포인터 변수만들 가지고서는 "실제 객체"가 뭔지 알 길이 없다.

이 포인터는 자신이 가르키키는 곳에 갔을 때 그곳에 Parent라는 애가 있다! 이렇게 보는 것인데

그러면 "진짜 실제 객체"는 뭔데?

parent* 는 제일 앞에 parent만 있는것을 알 뿐이지 뒤에 뭐가 있는지 모름.

그래서 문제가 없었는데 실제 진짜 뭔지는 모름.

=> 해결해야함.

실제 객체가 뭔지 해결.

  1. parent객체의 Output함수 호출

  2. pParent 포인터가 parent 객체의 주소를 받음.

  3. 객체의 주소에 접근을 하여 함수 호출


  1. child 객체의 함수 호출

  2. pParent 포인터가 child객체의 주소를 받음

  3. pParent 포인터(child 주소에)접근하여 함수 호출. (그러면 child의 output호출 되야함)

그런데 3번의 경우 child의 Output 함수가 호출이 안되고

parent의 output함수가 호출이 된다.

이렇게 찍힌다.

이유 ❗❗❗

실제 객체 정체가 child이여도 제일 앞에 parent객체가 메모리상으로 제일 앞에 오기 때문에

아무런 문제가 없이 너무나도 당연하게 Parent 쪽 함수가 호출되는 것이다.

pParent는 child객체의 주소를 가르키고 있지만 child객체의 앞에오는 주소는 Parent 이기 때문이다.

이런 느낌임.

가상함수

그래서 다 parent 포인터로 다 통일 되게 생겨버려서

해결할 수 있는

"가상 함수"라는 것을 제공을 한다.

class Parent
{
private:
	int m_value_1;
public:
	Parent()  
		:
		m_value_1(10)
	{
		cout << "Parent 생성자" << endl;
	}

public:
	virtual void Test()
	{
		cout << "Parent Test" << endl;
	}

};

이렇게 Parent쪽에 Test함수에 virtual 키워드를 붙여주게 되면은

이제는


Parent parent;
Child child;

Parent* pParent = nullptr;

parent.Test();
pParent = &parent;
pParent->Test();

child.Test();
pParent = &child;
pParent->Test();
   

이렇게 실행해보아도

컴파일러가 실제 객체인 child쪽의 Test 함수를 찾아서 호출하였다.

나는 그냥 C#에서 Creature라는 스크립트에 virtual Move라는 함수 만들어놓고

이것의 파생되는 클래스에서 각자 나름대로의 방법대로 구현을 하라는 의미에서 이렇게 해주었었다.

그러면 이제 가상함수 동작원리를 알아보도록 하자.

profile
https://cjbworld.tistory.com/ <- 이사중

0개의 댓글