C++ Chapter 12.2 : 가상 함수와 다형성

Date:     Updated:

카테고리:

태그:

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


chapter 12. 가상 함수들 : 가상 함수와 다형성

🔔 virtual 유무의 차이

가상함수 안 썼을 때

  • D가 C를 상속하고, C는 B를 상속하고, B는 A를 상속하는 구조
  • A의 대대 손손 자손들인 B, C, D는 모두 print()를 오버라이딩 하고 있다.
#include <iostream>
using namespace std;

class A
{
public:
	void print() { cout << "A" << endl; }
};

class B : public A
{
public:
	void print() { cout << "B" << endl; }
};

class C : public B
{
public:
	void print() { cout << "C" << endl; }
};

class D : public C
{
public:
	void print() { cout << "D" << endl; }
};

int main()
{
	A a;
	B b;
	C c;
	D d;

    A &ref1 = b;
    ref1.print();  // "A" 출력

	C &ref2 = d;
	ref2.print();  // "C" 출력

	return 0;
}
  • C++은 참조하거나 가리키는 객체의 타입이 아니라, 참조하는 **변수 혹은 포인터의 타입**이 무엇이냐에 따라 멤버를 호출하기 때문에
    • B타입 객체인 b를 참조하고 있더라도 ref1은 A타입이기 때문에 ref1.print(); A의 print()을 호출한다.
    • D타입 객체인 d를 참조하고 있더라도 ref2은 C타입이기 때문에 ref2.print(); C의 print()을 호출한다.

가상함수 썼을 때

#include <iostream>
using namespace std;

class A
{
public:
	virtual void print() { cout << "A" << endl; }
};

class B : public A
{
public:
	void print() { cout << "B" << endl; }
};

class C : public B
{
public:
	void print() { cout << "C" << endl; }
};

class D : public C
{
public:
	void print() { cout << "D" << endl; }
};

int main()
{
	A a;
	B b;
	C c;
	D d;

    A &ref1 = c;
    ref1.print();  // "C" 출력

	C &ref2 = d;
	ref2.print();  // "D" 출력

	return 0;
}

가상 함수 virtual

  1. virtual 가상 함수로 지정된 함수를 호출할 땐, 원래의 C++과 반대로, 변수가 아닌 참조하는 객체의 타입이 무엇이냐에 따라 호출한다.
    • 즉, 부모 포인터로 호출하더라도 자식이 오버라이딩한 함수를 호출한다.
    • ref1.print(); print()는 가상함수이므로 ref1은 C타입 객체인 c를 참조하기 때문에 C에서 오버라이딩된 print()를 호출한다. ref2도 마찬가지!
  2. 조상 클래스 virtual 가상 함수는 대대손손 유지된다.
    • 따라서 조상클래스의 가상함수를 자손 클래스들에게 물려주어도 자식 클래스에서 virtual을 붙여 주지 않더라도 그대로 가상함수다.
    • A 클래스의 print()에만 virtual을 붙여도 B, C, D에서 오버라이딩 한 print()들도 모두 가상 함수라는 특성이 유지된다.
        class A
        {
        public:
         virtual void print() { cout << "A" << endl; }
        };
      
    • 이렇게 virtual속성 또한 대대손손 상속이 되기 때문에 C타입인 ref2로 print()를 호출하더라도 참조하는 객체의 타입인 D타입의 print()를 호출한다.


🔔 주의사항

  1. 오버라이딩 할 땐 리턴까입까지도 꼭 같아야한다.
    • 오버로딩시엔 리턴타입은 고려대상이 아니지만.
  2. virtual 가상 함수는 스택처럼 쌓아서 처리되는게 아니라 가상함수표를 사용하여 조상으로 찾아 올라가는 식이라 좀 느리다.


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

맨 위로 이동하기

댓글남기기