C++에서 추상클래스는 하나 이상의 순수 가상 함수를 포함하는 클래스이다.
순수 가상 함수 => 본체가 없으며 파생 클래스에서 반드시 구현해야 한다.
그래서 추상 클래스는 인스턴스화 될 수 없다.
C#, JAVA의 인터페이스 역확을 추상 클래스로 하면된다.
추상 클래스는 가상 함수, 순수 가상함수, 일반 함수, 멤버 변수, 정적 함수를 가질 수 있다.
가상함수 : 파생클래스에서 오버라이드 가능. 순수 가상 함수가 아니므로 기본 구현을 제공할 수 있다.
순수 가상 함수 : 파생클래스에서 반드시 구현해야 하는 함수.이 함수들이 클래스를 추상클래스로 만든다.
final 키워드가 붙지 않은 이상은 반드시 재정의 해줘야한다.
일반 함수 : 이러한 함수들은 오버라이드할 수 없다. 직접 구현된다.
일반 함수는 파생 클래스에서 오버라이딩할 수 없고 파생 클래스에서 동일한 이름과 시그니처를 가진 함수를 정의한다면
이는 새로운 함수를 제공하는 것으로 간주된다.
오버로딩과 비슷한 개념일 수 있지만 실제로는 서로 다른 스코프에 속한 별개의 함수를 정의하는 것이라고 한다.
멤버 변수 : 추상 클래스도 멤버 변수를 가질 수 있다.
정적 함수 : 클래스 인스턴스 없이 호출될 수 있는 함수
함수 선언 끝에 = 0을 붙여서 만든다.
virtual void SetPrice(int myPrice) = 0;
fianl 키워드를 사용하면 재정의(오버라이드)가 불가능하다.
virtual void SetPrice(int myPrice) final; // 가상함수
virtual void SetPrice(int myPrice)= 0 final; // 순수 가상 함수
class AbstractClass {
public:
// 순수 가상 함수
virtual void pureVirtualFunction() = 0;
// 가상 함수
virtual void virtualFunction() {
std::cout << "This is a virtual function with an implementation." << std::endl;
}
// 일반 함수
void normalFunction() {
std::cout << "This is a normal function." << std::endl;
}
// 정적 함수
static void staticFunction() {
std::cout << "This is a static function." << std::endl;
}
};
순수 가상 함수와 일반 함수
class Base {
public:
void regularFunction() {
std::cout << "Base regularFunction" << std::endl;
}
virtual void virtualFunction() = 0;
};
class Derived : public Base {
public:
// 이 일반함수는 Derived 클래스의 함수.
void regularFunction() {
std::cout << "Derived regularFunction" << std::endl;
}
void virtualFunction() override {
std::cout << "Derived virtualFunction" << std::endl;
}
};
함수를 오버라이드할 때 꼭 override 키워드를 사용해야하는 것은 아니다.
하지만 사용하는 것이 좋은 관행이라고 한다.
override 를 사용하면
오버라이드 의도 검증: 파생 클래스의 함수가 기반 클래스의 가상 함수를 실제로 오버라이드하는지 확인한다. 함수 시그니처가 정확히 일치하지 않는 경우(예: 매개변수 타입 불일치, 상수성 불일치 등), 컴파일러는 오류를 발생시킨다.
기반 클래스 함수의 가상성 확인: override 키워드가 사용된 함수는 반드시 기반 클래스의 가상 함수를 오버라이드해야 한다. 만약 기반 클래스에 해당 시그니처의 가상 함수가 없다면 컴파일러는 오류를 발생시킨다.
class Base {
public:
virtual void func();
};
class Derived : public Base {
public:
void func() override; // 이 함수는 Base::func를 오버라이드함을 명시
};
override 키워드 사용은 가독성과 안정성을 높이는 좋은 방법이니 사용하도록 하자.