C++ 초급 - 8. 객체지향 프로그래밍 (5 - C++11의 override와 final)
2025. 2. 22. 15:48ㆍ프로그래밍 언어/C++
📌 8.5 C++11의 override와 final
C++11에서는 가상 함수 오버라이딩을 더 명확하고 안전하게 수행하기 위해 override 키워드와 final 키워드가 추가되었다.
이를 통해 컴파일러가 오버라이딩 오류를 검출할 수 있으며, 클래스나 함수의 상속 및 재정의를 제한할 수도 있다.
📌 1. override 키워드의 필요성
🔹 (1) override란?
- 부모 클래스의 virtual 함수를 자식 클래스에서 재정의할 때 명확하게 표시하는 키워드.
- 컴파일러가 오버라이딩 여부를 검사하므로 실수 방지 가능.
- 부모 클래스에 해당 함수가 없으면 컴파일 오류 발생.
🔹 (2) override 없이 발생하는 문제
- 부모 클래스의 가상 함수 이름을 잘못 입력하거나, 매개변수 리스트가 다르면 오버라이딩되지 않음.
- 하지만, C++11 이전에는 이를 검출할 방법이 없었음.
💡 예제: override 없이 발생하는 실수
#include <iostream>
class Base {
public:
virtual void showMessage() { std::cout << "Base 클래스" << std::endl; }
};
class Derived : public Base {
public:
void showMessage(int x) { std::cout << "Derived 클래스" << std::endl; } // ❌ 오버라이딩 아님 (매개변수 다름)
};
int main() {
Base* obj = new Derived();
obj->showMessage(); // ✅ "Base 클래스" (Derived의 함수가 호출되지 않음)
delete obj;
return 0;
}
🔹 출력 결과
Base 클래스
💡 설명
- Derived 클래스의 showMessage(int x)는 부모 클래스의 showMessage()를 재정의하려 했지만, 매개변수가 다르므로 오버라이딩되지 않음.
- 따라서 Base의 showMessage()가 호출됨.
🔹 (3) override를 사용한 올바른 오버라이딩
- override를 사용하면 부모 클래스의 가상 함수가 정확히 존재하는지 컴파일러가 검사.
- 만약 함수명이 다르거나 매개변수가 다르면 컴파일 오류 발생.
💡 예제: override 사용
#include <iostream>
class Base {
public:
virtual void showMessage() { std::cout << "Base 클래스" << std::endl; }
};
class Derived : public Base {
public:
void showMessage() override { std::cout << "Derived 클래스" << std::endl; } // ✅ 올바른 오버라이딩
};
int main() {
Base* obj = new Derived();
obj->showMessage(); // ✅ "Derived 클래스" (정상적으로 오버라이딩됨)
delete obj;
return 0;
}
🔹 출력 결과
Derived 클래스
💡 설명
- Derived의 showMessage()에서 override를 사용함으로써 부모 클래스의 함수와 정확히 일치하는지 확인 가능.
- override가 없다면, 오타나 매개변수 차이로 인해 의도하지 않은 동작이 발생할 수도 있음.
🔹 (4) override 미사용 시 발생하는 컴파일 오류
💡 오류 예제
class Derived : public Base {
public:
void showmessage() override { std::cout << "Derived 클래스" << std::endl; } // ❌ 오타 발생 (Base 클래스에는 "showMessage" 존재)
};
🔹 컴파일 오류 메시지
error: ‘void Derived::showmessage()’ marked ‘override’, but does not override any member functions
💡 설명
- override 키워드 덕분에 부모 클래스에 showMessage()가 존재하지 않으면 컴파일 오류 발생.
- 실수를 미리 방지할 수 있음.
📌 2. final 키워드의 필요성
🔹 (1) final이란?
- 더 이상 상속받거나, 오버라이딩할 수 없도록 제한하는 키워드.
- 클래스에 사용하면 상속 금지,
함수에 사용하면 오버라이딩 금지.
🔹 (2) final을 사용하여 상속 금지
- final을 사용하면 특정 클래스를 더 이상 상속받지 못하게 설정 가능.
💡 예제: final을 사용하여 클래스 상속 금지
class Base final { // ✅ 이 클래스를 상속받을 수 없음
public:
void show() { std::cout << "Base 클래스" << std::endl; }
};
/*
class Derived : public Base { // ❌ 오류 발생! (Base는 final 클래스)
};
*/
int main() {
Base obj;
obj.show();
return 0;
}
🔹 컴파일 오류 발생
error: cannot derive from ‘Base’ as it has been declared ‘final’
💡 설명
- class Base final로 선언하면 이 클래스를 상속받는 것이 불가능.
- 특정 클래스를 더 이상 확장하지 않도록 제한할 때 사용.
🔹 (3) final을 사용하여 함수 재정의(오버라이딩) 금지
- final을 사용하면 자식 클래스에서 특정 함수를 오버라이딩할 수 없도록 설정 가능.
💡 예제: final을 사용하여 함수 오버라이딩 금지
#include <iostream>
class Base {
public:
virtual void showMessage() final { std::cout << "Base 클래스" << std::endl; } // ✅ 이 함수는 더 이상 오버라이딩 불가
};
class Derived : public Base {
public:
/*
void showMessage() override { // ❌ 오류 발생! (Base에서 final로 선언됨)
std::cout << "Derived 클래스" << std::endl;
}
*/
};
int main() {
Base obj;
obj.showMessage();
return 0;
}
🔹 컴파일 오류 발생
error: virtual function ‘virtual void Derived::showMessage()’ overriding final function
💡 설명
- showMessage()를 final로 선언하면 파생 클래스에서 오버라이딩할 수 없음.
- 기능을 확장하지 못하도록 제한하고 싶을 때 사용.
📌 3. 정리
개념 | 설명 |
override 키워드 | 부모 클래스의 가상 함수를 정확히 오버라이딩했는지 검사 |
override의 필요성 | 오버라이딩 실수를 방지 (부모 클래스에 동일한 함수가 없으면 컴파일 오류 발생) |
final 키워드 | 클래스나 함수의 상속 및 오버라이딩을 금지 |
클래스에 final 적용 | class Derived final { ... }; → 이 클래스를 상속받을 수 없음 |
함수에 final 적용 | void func() final; → 이 함수를 오버라이딩할 수 없음 |
'프로그래밍 언어 > C++' 카테고리의 다른 글
C++ 초급 - 9. 템플릿 기초 (1 - 함수 템플릿 (Function Template)) (0) | 2025.02.22 |
---|---|
C++ 초급 - 8. 객체지향 프로그래밍 (6 - explicit 생성자 (C++11)) (0) | 2025.02.22 |
C++ 초급 - 8. 객체지향 프로그래밍 (4 - 인터페이스 개념 (Interface)) (0) | 2025.02.22 |
C++ 초급 - 8. 객체지향 프로그래밍 (3 - 순수 가상 함수 (= 0)) (0) | 2025.02.22 |
C++ 초급 - 8. 객체지향 프로그래밍 (2 - virtual 함수와 오버라이딩 (Overriding)) (0) | 2025.02.22 |