컴파일 시점이란?
코드에 대해 구체적인 타입이 결정되는 시점
-> 아래의 코드에서 a객체는 Animal타입임을 알기 때문에, Animal 클래스의 Speak()를 호출한다고 결정한다
-> 프로그램 실행 전 <컴파일>
#include <iostream>
using namespace std;
class Animal {
public:
void speak() { // 가상 함수가 아님
cout << "Animal speaks!" << endl;
}
};
class Dog : public Animal {
public:
void speak() { // Animal의 speak()를 오버라이드
cout << "Dog barks!" << endl;
}
};
int main() {
Animal* animal = new Dog(); // Animal 포인터가 Dog 객체를 가리킴
animal->speak(); // "Animal speaks!"가 출력됨 (정적 바인딩)
return 0;
}
런타임시점이란?
-> 프로그램이 실제로 실행되는 시점이다
-> 실제 객체가 무엇인지에 따라 동작이 결정된다
아래의 예시에서 animal 포인터가 Dog( )객체를 가리키고 있고 함수를 호출했을때, Animal에 가상함수로 정의되어 있다면 컴파일러는 런타임(실행)중에 실제 객체를 확인한 뒤 실제 객체의 함수를 호출한다
#include <iostream>
using namespace std;
class Animal {
public:
virtual void speak() { // 가상 함수
cout << "Animal speaks!" << endl;
}
};
class Dog : public Animal {
public:
void speak() override { // 가상 함수 오버라이딩
cout << "Dog barks!" << endl;
}
};
int main() {
Animal* animal = new Dog(); // Animal 포인터가 Dog 객체를 가리킴
animal->speak(); // "Dog barks!"가 출력됨 (동적 바인딩)
return 0;
}
정말정말 쉽게 말하자면 
만약, virtual(가상함수)를 사용하지 않을 경우, Animal* animal = new Dog();로 Animal포인터가 Dog객체를 가리키는 상태여도, 정적바인딩이기 때문에 컴파일 시점에 이미 animal포인터의 타입은 Animal이라고 결정이 난 상태인 것
-> 함수를 호출하면 Animal클래스의 함수가 호출될 것임
만약, virtual(가상함수)를 사용 할 경우, 똑같이 Animal* animal = new Dog();로 Animal포인터가 Dog객체를 가리키는 상태이다.
하지만, 가상함수를 사용하면 동적바인딩으로 런타임 시점에 실제 객체가 무엇인지에 따라 함수 호출이 결정된다
객체가 생성되고 가리키고 있는 실제 객체의 함수가 호출된다
💡 한 마디로:
"virtual을 선언하면, 실행 중(런타임)에 실제 객체를 확인해서 함수를 호출한다!" 🚀