C++ Chapter 12.9 : 객체 잘림과 reference_wrapper
카테고리: Cpp
태그: Cpp Programming
인프런에 있는 홍정모 교수님의 홍정모의 따라 하며 배우는 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() 호출.
- Derived만의 부분들 (Derived에서 오버라이딩 한것, 상속 받은 것이 아닌 Derived만의 멤버들) 은 잘려 버리고 Base로부터 상속받은 부분들만
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 타입을 참조 형태로 리턴 받아 다형성을 실현할 수 있다.
🌜 개인 공부 기록용 블로그입니다. 오류나 틀린 부분이 있을 경우
언제든지 댓글 혹은 메일로 지적해주시면 감사하겠습니다! 😄
댓글남기기