반응형
클래스의 상속관계에서 부모의 함수를 오버라이딩 하여 사용할 때가 있습니다.
만약 그 함수의 객체를 포인터로 만들었을 때 문제가 생길 수 있습니다. 다음의 코드를 보면서 이해해 보겠습니다.
class First
{
public:
void SimpleFunc() { cout << "First" << endl; }
};
class Second : public First
{
public:
void SimpleFunc() { cout << "Second" << endl; }
};
class Third : public Second
{
public:
void SimpleFunc() { cout << "Third" << endl; }
};
int main() {
Third* ptr3 = new Third();
Second* ptr2 = ptr3;
First* ptr1 = ptr2;
ptr1->SimpleFunc();
ptr2->SimpleFunc();
ptr3->SimpleFunc();
}
위 코드의 결과는 다음과 같습니다.
언뜻 보면 정상적인 결과로 보입니다. 하지만 이것이 문제가 되는 이유는 ptr3는 Third 클래스를 가리키는 포인터로 생성이 되었으니 ptr3 -> SimpleFunc() 했을 때 Third 가 나오는 게 정상입니다. 하지만 ptr2와 ptr1 은 객채의 생성은 Second와 First 클래스로 생성이 되었습니다. 하지만 포인터 객체 이므로 서로 가리키는 클래스가 각각
ptr2 -> ptr3 ( Third)
ptr1 -> ptr2 ( ptr3 -> Third 클래스 ) 가 됩니다. 하지만
SimpleFunc() 함수는 각각 생성된 클래스에 있는 함수가 불러와졌습니다.
문제없이 출력이 된것처럼 보이지만 사실 논리상 맞지 않습니다.
이러한 로직 에러를 방지하기 위해 C++에 있는 개념이 가상함수입니다.
예를 통해서 가상함수에 사용을 확인해 보겠습니다.
class First
{
public:
virtual void SimpleFunc() { cout << "First" << endl; }
};
class Second : public First
{
public:
virtual void SimpleFunc() { cout << "Second" << endl; }
};
class Third : public Second
{
public:
virtual void SimpleFunc() { cout << "Third" << endl; }
};
int main() {
Third* ptr3 = new Third();
Second* ptr2 = ptr3;
First* ptr1 = ptr2;
ptr1->SimpleFunc();
ptr2->SimpleFunc();
ptr3->SimpleFunc();
}
실행결과는 다음과 같습니다.
가상함수를 사용하면 포인터 클래스 객채 생성 시 클래스 타입이 아닌 포인터가 가리키는 클래스를 할당받아 그 객체에 함수나 멤버 변수에 참조를 하게 해주는 기능입니다.
반응형
'c++ > 상속과 다형성' 카테고리의 다른 글
[C++] 객체 포인터의 참조관계 (0) | 2023.01.15 |
---|