C++ Chapter 12.9 : 객체 잘림과 reference_wrapper

Date:     Updated:

카테고리:

태그:

인프런에 있는 홍정모 교수님의 홍정모의 따라 하며 배우는 C++ 강의를 듣고 정리한 필기입니다. 😀
🌜 [홍정모의 따라 하며 배우는 C++]강의 들으러 가기!


chapter 12. 가상 함수들 : 객체 잘림과 reference_wrapper

객체 잘림 : 부모에 자식을 구겨 넣을 때 발생한다.

  • 자식 타입 객체가 부모 타입 객체보다 메모리 용량이 더 크다.
    • 부모 타입 객체를 포함하기 떄문에.
#include <iostream>
#include <vector>
#include <functional> // reference_wrapper 용

using namespace std;

class Base
{
public:
	int m_i = 0;

	virtual void print()
	{
		cout << "I'm Base" << endl;
	}
};

class Derived : public Base
{
public:
	int m_j = 1;

	virtual void print() override
	{
		cout << "I'm derived" << endl;
	}
};


🔔 부모 타입의 포인터 & 참조로 자식 객체 가리키기

Base & b1 = derived;
Base * b2 = new Derived();

부모 타입의 포인터 Object *참조 Object & 변수로 자식 객체를 가리킬 땐 객체 잘림 없이 다형성을 실현한다

int main()
{
	Derived d;
	Base & b1 = d;

	b.print();  

	return 0;
}
💎출력💎

I'm Derived
  • 단순히 b1라는 참조 변수가 Derived 타입의 객체 d가리키고 있을 뿐이기 때문에 더 작은 메모리(부모)에 자식 객체를 구겨 넣어 객체가 잘리는 일이 없다.
    • 따라서 부모 타입의 포인터나 참조 변수로 자식 객체가 오버라이딩 한 내용을 호출할 수 있으며(단, 가상 함수 일때.) 이를 다형성이라고 한다.


🔔 부모 타입의 객체에 자식 객체 집어 넣기 : 객체 잘림 발생

Base b = d;

위와 같이 그냥 부모 객체에 자식 객체를 우겨 넣으려고 하면 객체 잘림 현상이 발생하며 다형성을 실행할 수 없다.

int main()
{
	Derived d;
	Base b = d;

	b.print();  

	return 0;
}
💎출력💎

I'm Base
  • Base b = d 👉 b가 부모인 Base 타입이라 d보다 메모리 용량이 작은데 d를 우겨넣으려니 객체 잘림 현상이 발생한다.
    • Derived만의 부분들 (Derived에서 오버라이딩 한것, 상속 받은 것이 아닌 Derived만의 멤버들) 은 잘려 버리고 Base로부터 상속받은 부분들만 b에 들어가게 된다.
    • “I’m Base” 출력
      • print()가 가상 함수고 오버라이딩이 되어있었더라도 Derived 부분들은 다 잘려나갔기 때문에 Base의 print() 호출.

void func(Base b) 이런식으로 인수를 참조나 포인터가 아닌 그냥 객체로 받는 경우, 객체 잘림 현상에 주의해야 한다. 다형성이 실행되지 않는다.


🔔 reference_wrapper

std::reference_wrapper<Base>

  • #include <functional>을 해주어야 사용 가능하다.
  • 일반 객체를 참조 형태로 리턴해주는 역할을 한다.
Base b;
Derived d;

std::vector<Base*> my_vec;
my_vec.push_back(&b);
my_vec.push_back(&d);

for (auto & ele : my_vec)
    ele->print();

std::vector는 참조 형태의 원소는 받지 않는다. 따라서 다형성을 위해 위와 같이 포인터로 넣어줄 수도 있지만

Base b;
Derived d;

std::vector<std::reference_wrapper<Base>> my_vec;
my_vec.push_back(b);
my_vec.push_back(d);

for (auto & ele : my_vec)
    ele.get().print();

꼭 참조 형태로 넣어주고 싶다면 위와 같이 reference_wrapper를 사용하여 그냥 객체인 Base 타입을 참조 형태로 리턴 받아 다형성을 실현할 수 있다.



🌜 개인 공부 기록용 블로그입니다. 오류나 틀린 부분이 있을 경우 
언제든지 댓글 혹은 메일로 지적해주시면 감사하겠습니다! 😄

맨 위로 이동하기

Cpp 카테고리 내 다른 글 보러가기

댓글 남기기