C++11에서 도입된 override와 final 키워드는 가상 함수(virtual function)의 오버라이딩(재정의)과 관련된 중요한 기능을 제공합니다.
✅ override: 부모 클래스의 가상 함수를 올바르게 재정의했는지 확인하는 키워드.
✅ final: 특정 함수나 클래스를 더 이상 재정의(오버라이딩)하거나 상속할 수 없게 만드는 키워드.
이 문서에서는 override와 final의 필요성, 사용법을 예제 코드와 함께 상세히 분석하겠습니다.
Creatureclass Creature
{
public:
virtual void Attack()
{
cout << "Creature!" << endl;
}
};
✅ Creature 클래스
Creature는 기본 클래스(Base Class)입니다. Attack virtual 키워드가 붙어 있어 자식 클래스에서 오버라이딩 가능. Attack이 호출되면 "Creature!"를 출력합니다. Player 클래스class Player : public Creature
{
public:
virtual void Attack() override
{
cout << "Player!" << endl;
}
};
✅ Player 클래스 (파생 클래스)
Player는 Creature을 상속받아 새로운 기능을 추가합니다. override 키워드 사용 override를 붙이면 부모 클래스의 가상 함수를 올바르게 재정의했는지 컴파일러가 확인합니다. Attack 함수 호출 시 "Player!"가 출력됩니다. Knight 클래스class Knight : public Player
{
public:
virtual void Attack() override
{
cout << "Knight!" << endl;
}
};
✅ Knight 클래스 (파생 클래스)
Knight는 Player 클래스를 상속받아 기능을 추가. override를 사용하여 Attack을 재정의. Attack 함수 호출 시 "Knight!"가 출력됩니다. final 키워드class Knight : public Player
{
public:
virtual void Attack() override final
{
cout << "Knight!" << endl;
}
};
✅ final 키워드 추가
override final을 사용하면 자식 클래스에서 Attack을 더 이상 오버라이딩할 수 없음. final이 붙은 Attack을 오버라이딩하려 하면 컴파일 에러 발생. class SuperKnight : public Knight
{
public:
// ERROR! 'Attack' is final in 'Knight'
virtual void Attack() override // ❌ 컴파일 에러 발생
{
cout << "SuperKnight!" << endl;
}
};
💡 final을 사용하면 예상치 못한 함수 오버라이딩을 방지하고 코드의 안정성을 높일 수 있음.
main() 함수 분석int main()
{
Player* player = new Knight();
player->Attack();
return 0;
}
✅ 다형성(Polymorphism) 활용
Player* player = new Knight();: Player 포인터가 Knight 객체를 가리킴. player->Attack(); Knight의 Attack이 실행됨. Knight!Attack()이 최종적으로 호출됨.override와 final 비교| 기능 | override | final |
|---|---|---|
| 용도 | 올바른 오버라이딩인지 검증 | 오버라이딩을 차단 |
| 사용 위치 | 가상 함수(virtual function) | 가상 함수 또는 클래스 |
| 컴파일 에러 발생 여부 | 잘못된 오버라이딩 시 컴파일 에러 | 오버라이딩을 시도하면 컴파일 에러 |
| 가독성 향상 | 부모 함수와의 관계를 명확히 함 | 더 이상 변경되지 않는 함수임을 명확히 표현 |
✅ override는 재정의(Overriding)한 함수가 부모의 가상 함수와 정확히 일치하는지 검증.
✅ final은 특정 함수(또는 클래스)의 상속/오버라이딩을 금지하여 코드 안정성을 높임.
final 클래스 예제class FinalClass final
{
public:
void SayHello()
{
cout << "Hello from FinalClass!" << endl;
}
};
// ERROR! FinalClass를 상속할 수 없음
class Derived : public FinalClass
{
};
✅ 클래스 자체를 상속 금지
FinalClass는 final이므로 더 이상 상속할 수 없음. Derived 클래스를 정의하려 하면 컴파일 에러 발생. const를 사용한 함수 오버로딩class Player
{
public:
virtual void Attack() { cout << "Player!" << endl; }
};
class Knight : public Player
{
public:
virtual void Attack() const // ❌ 부모 함수와 시그니처가 다름
{
cout << "Knight!" << endl;
}
};
✅ const를 붙이면 부모 클래스의 함수와 다른 함수로 간주됨
✅ 함수 시그니처가 다르므로 override가 적용되지 않음
✅ 오버라이딩을 원하면 부모 함수에도 const를 추가해야 함