반응형
가상 함수란
- 가상함수는 부모 클래스에서 상속받을 클래스에서 재정의할 것으로 기대하고 정의해놓은 함수이다.
- virtual이라는 예악어를 함수 앞에 붙여서 생성할 수 있으며 이렇게 생성된 가상함수는 파생 클래스에서 재정의하면 이전에 정의되었던 내용들은 모두 새롭게 정의된 내용들로 교체된다.
이렇게 설명을 들으면 오버라이딩이랑 비슷하다고 생각할 수 있는데 아니다.
- 일단 가상 함수를 쓰는 이유는 업 캐스팅을 할 때 많이 사용하는 것으로 생각하면 될 것이다
- 업 캐스팅이란?
- 부모 클래스를 가리키는 포인터를 선언한 후 그 변수에 자식을 넣어주는 것이다.
- 업 캐스팅이란?
코드를 보며 설명을 해보겠다.
class Animal
{
int hp;
int hunger;
virtual ~Animal();
virtual getHP()
return hp;
}
8byte
class Dog : Animal
{
vtable *vtable;
int b;
//int *a = new int[6];
//Aniaml *ptr = new Animal();
getHP(){
return hp * 2;
}
}
8 + 4byte = 12
Animal *dog = new Dog();
Dog(dog);
delete dog;
dog->getHP();
dog->vtable->getHP()
{
Dog d;
Animal *ptr = &d;
}
- 현재 Animal이라는 부모 클래스, Dog라는 자식 클래스가 있다.
- 메모리 상에서 클래스를 보자
- Animal에는 int 변수 hp와 hunger이 있다. 이로 인해 8바이트가 생성되며, Dog는 Animal을 상속 받기 때문에 8 + int b 변수 12바이트가 생성이 된다.
- 그 후 Animal *dog = new Dog(); 이라는 것을 선언한다. 이렇게 되면 컴파일러는 Animal이라는 친구로 바로 간다고 생각을 하는데 함수를 통해 이해해보자.
- 보통은 dog에 자식 Dog 클래스를 넣었기 때문에 값이 getHp이라는 함수를 불렀을 때 자식의 getHp를 부른다고 생각한다. 하지만 결과를 보면 부모에 있는 getHp가 불러와질 것이다.
- 자식에 있는 getHP를 부르고 싶으면 가상 함수를 사용해야한다. 함수 앞에 virtual를 붙여준다. virtual getHP();
가상 함수 선언 후 vtable
이렇게 가상 함수를 선언하면 자식 클래스에서 vtable이라는 친구를 생성하게 되는데 아까 위에서 메모리로 봤을 때 12byte가 선언된다고 했는데 vtable 생성으로 8byte가 추가적으로 생성된다.
- vtable 안에는 getHp가 함수가 들어가게 된다.
- 그 후, dog가 가리키는 getHp를 부르면 자식에 있는 getHp를 불러오게 된다.
- 어떻게 가능할까? vtable안에 자식에 선언된 getHp의 주소를 넣어주고
- 컴파일러가 Animal 부모 클래스를 가기 전에 자식에 있는 vtable을 보고 간다. 그래서 자식의 getHp가 가능하다.
소멸자 가상 함수
- 소멸자에 가상 함수를 붙여주는 이유는 메모리 상에서 봤을 때 소멸자가 가상 함수 vtable에 없으면 자식에서 부모를 그대로 복사한 부분을 지워주지 못 한다. 동적 할당을 할 경우에 메모리 누수가 난다. 그래서 무조건 소멸자를 가상 함수를 붙여준다.
이 분의 글을 통해 공부하였습니다.
반응형
'C++ > C++ 가상 함수, 순수 가상 함수, 추상 클래스' 카테고리의 다른 글
순수 가상 함수, 추상 클래스 (0) | 2024.01.25 |
---|