오버라이딩(overriding) - 상위클래스의 함수를 하위클래스에서 재정의 해서 사용
오버로딩(overloading) - 같은이름의 함수를 매개변수 개수 또는 타입을 다르게하여 여러개의 함수를 정의
virtual 키워드 - 컴파일러에게 자신에 대한 호출 바인딩을 실행 시간까지 미루도록 지시하는 키워드
가상함수 - 부모 클래스에서 상속받을 클래스에서 재정의할 것으로 기대하고 정의해놓은 함수
⇒순수 가상함수 - 함수의 몸체를 정의 안함
⇒일반 가상함수 - 함수의 몸체를 정의함
virtual - 가상 함수를 가르키는 키워드 (부모 클래스 함수앞에 붙인다)
override - 부모 클래스의 함수를 재선언 및 재정의 (자식 클래스 함수 뒤에 붙인다, override된 함수를 호출할 경우 부모 클래스의 함수는 무시됨)
final - 가상 함수의 마지막을 가르키는 키워드 (더 이상 가상함수를 오버라이딩 하지 않음)
virtual 없이 override 하는 경우에는 기본 클래스 포인터로 override한 함수를 호출할 수 없다
#include <iostream>
using namespace std;
class A
{
public:
void test(){
cout << "a" << endl;
}
};
class B : public A
{
public:
void test() {
cout << "b" << endl;
}
};
class C : public B
{
public:
void test(){
cout << "c" << endl;
}
};
int main(){
A *a;
B *b;
C *c;
a -> test();
a = new B();
a -> test();
a = new C();
a -> test();
cout << endl;
b -> test();
b = new C();
b -> test();
cout << endl;
c -> test();
}

B 클래스의 test함수만 가상함수로 만들었다
#include <iostream>
using namespace std;
class A
{
public:
void test(){
cout << "a" << endl;
}
};
class B : public A
{
public:
virtual void test() {
cout << "b" << endl;
}
};
class C : public B
{
public:
void test() override{
cout << "c" << endl;
}
};
int main(){
A *a;
B *b;
C *c;
a -> test();
a = new B();
a -> test();
a = new C();
a -> test();
cout << endl;
b = new B(); // 가상함수는 동적할당이어서 메모리할당해주어야한다.
b -> test();
b = new C();
b -> test();
cout << endl;
c = new C(); // 가상함수는 동적할당이어서 메모리할당해주어야한다.
c -> test();
}
출처: https://flower0.tistory.com/234 [개발자 라면]
-----------------------------------------------------------------------------------

-> virtual 키워드를 부모 클래스 앞에 붙여주면, 함수 호출시 자식 클래스의 함수가 호출됨
그런데 자식 클래스 함수에 override 를 없애주어도 똑같이 작동한다
그러면 override는 어쩔때 쓰는것일까
class A
{
public:
void test(){
cout << "a" << endl;
}
};
class B : public A
{
public:
virtual void test() {
cout << "b" << endl;
}
};
class C : public B
{
public:
void test(int a){
cout << "c" << endl;
}
};
B클래스 test(void)와 C클래스 test(int)의 매개변수를 달리하여 함수를 정의하였다.
이것은 매개변수 타입을 달리하여 override 규칙을 무시한 것이다.
b = new B();
b -> test();
b = new C();
b -> test();
C클래스 에서 재정의한 b->test() 를 실행시켜보면은

C클래스에서 재정의한 int를 매개변수로 받는 test함수를 인식하지못하여 b가 출력되는것이다
이때 override를 사용하면

에러가 출력되는것을 확인할 수 있다.
매개변수가 서로다른 함수를 재정의할때 override를 사용하게끔 하여 가독성을높이고 재정의를 하는데 인자를 더 넣는다거나 반환형이 다르게 만든다거나 하는 실수를 컴파일러가 잡아낼수있는 것이다. (안전한 코딩이 가능)
c++ 에서 오버라이드 하기위해선
부모클래스의 함수앞에 virtual - (필수)
자식클래스의 함수뒤에 override - (선택) 하지만 안전한 코딩을 위한 사용이 권장됨
또한 순수가상함수는 자식클래스에서 '무조건' 재정의해야하는 함수
함수만 있고 본체가 없다는 의미로 함수 선언부 끝에 "=0"을 추가
class A
{
public:
void test(){
cout << "a" << endl;
}
};
class B : public A
{
public:
virtual void test() = 0;
};
class C : public B
{
public:
void test() {
cout << "c" << endl;
}
};
int main(){
A *a;
B *b;
C *c;
a -> test();
a = new B();
a -> test();
a = new C();
a -> test();
cout << endl;
b = new B();
b -> test();
b = new C();
b -> test();
c = new C();
c -> test();
}
순수가상함수를 가지고있는 B클래스는 객체생성자체가 불가능하다.
이렇게 하나 이상의 순수 가상 함수를 포함하는 B클래스를 추상 클래스(abstract class)라고한다.
다음 예제는 비쥬얼스튜디오 공식 문서에있는 override 예제이다
class BaseClass
{
virtual void funcA();
virtual void funcB() const;
virtual void funcC(int = 0);
void funcD();
};
class DerivedClass: public BaseClass
{
void funcA() override; // 부모의 funcA()와 동일한 함수
void funcB() override; // 부모의 funcB()는 const 함수
// 자식의 funcB()와는 다른함수이다.
// 컴파일 에러
void funcB() const override; // 부모의 funcB() const와
// 자식의 funcC() const가 동일하다
void funcC( double = 0.0 ) override; // 부모의 funcC()와 자식의 funcC()의 인자타입이 다르다.
// 컴파일 에러
void funcD() override; // 부모의 funcD()함수가 가상함수가 아니기때문에 오버라이드 불가
// 컴파일 에러
};
'프로그래밍 > C++' 카테고리의 다른 글
this 포인터, 연산자 오버로딩 (0) | 2022.04.15 |
---|---|
멤버 초기화 리스트, 이니셜라이저 (0) | 2022.04.13 |
const / constexpr / #define (0) | 2022.04.12 |
C++ 상속 (0) | 2022.04.08 |
NULL / nullptr (0) | 2022.03.18 |