객체 슬라이싱
Base value로 받으면 파생 부분이 잘려 다형성이 깨질 수
있습니다.
virtual 함수는 기반 포인터나 참조에서도 실제 객체의
override를 선택합니다. 같은 이유로 기반 클래스 소멸자도
virtual이어야 안전하게 정리됩니다.
호출 코드는 기반 타입 인터페이스만 알고 있습니다.
컴파일러는 정적 호출 대신 동적 디스패치 경로를 사용합니다.
실제 객체가 가진 테이블을 통해 override 주소를 찾습니다.
런타임 실제 타입에 맞는 함수가 실행됩니다.
Base value로 받으면 파생 부분이 잘려 다형성이 깨질 수
있습니다.
delete Base*에서 파생 소멸자가 호출되지 않아 자원
누수가 생길 수 있습니다.
시그니처 실수를 컴파일 시점에 잡도록 파생 함수에
override를 붙입니다.
Base 값보다 Base&,
const Base&, Base*를
사용합니다.
소유권이 필요하면 std::unique_ptr<Base> 같은
스마트 포인터를 검토합니다.
virtual로
둡니다.
인터페이스만 제공할 때는 순수 가상 함수와 기본 소멸자를 함께
둡니다.
override를 붙여 의도와 시그니처를
명시합니다.
소멸자도 override로 표시하면 계층 구조를 읽기
쉬워집니다.
핵심은 virtual 자체보다 “기반 타입으로 호출하고 삭제해도
실제 객체의 동작과 정리가 보존되는가”를 확인하는 것입니다.