반응형
아래의 FOOD class와 상속 받은 SNACK class를 보자.
class FOOD
{
private:
int price = 0;
public:
FOOD() { printf("FOOD created\n"); }
~FOOD() { printf("FOOD deleted\n"); }
virtual void printName() { cout << "FOOD Class" << endl; }
virtual void printPrice() { cout << this->price << endl; }
void printLine() { cout << "=================" << endl; }
};
class SNACK : public FOOD
{
private:
int price = 1000;
public:
SNACK() { printf("SNACK created\n"); }
~SNACK() { printf("SNACK deleted\n"); }
void printName() { cout << "SNACK Class" << endl; }
void printPrice() { cout << this->price << endl; }
};
SNACK class가 상속받은 함수 뒤에 override 키워드를 추가하면 오버라이딩하는 것을 컴파일 시점에 확인할 수 있다.
class SNACK : public FOOD
{
...
void printName() override { cout << "SNACK Class" << endl; }
void printPrice() override { cout << this->price << endl; }
};
즉 override 불가능한 경우에는 컴파일 에러가 난다.
아래의 경우를 보자.
FOOD class의 printName은 인자가 없는데, override는 int가 있는 경우로 override 하고 있다.
printLine은 virtual 함수가 아닌데 override 하고 있다.
따라서 override 키워드가 컴파일 타임에 overriding을 잘못하고 있다고 알려준다.
두 경우 모두 override가 없으면 컴파일이 된다.
printName(int value)나 printLine()이 virtual이 아니므로
SNACK 타입의 SNACK 객체에서는 사용할 수 있기 때문이다.
정리하자면 다음과 같다.
FOOD* foodList[3];
foodList[2] = new SNACK();
foodList[2]->printPrice(5); // compile error
SNACK* snack = new SNACK();
snack->printName(); // compile error
코드를 실행해서 override의 차이를 비교해보자.
#include <stdio.h>
#include <iostream>
using namespace std;
class FOOD
{
private:
int price = 0;
public:
FOOD() { printf("FOOD created\n"); }
virtual ~FOOD() { printf("FOOD deleted\n"); }
virtual void printName() { cout << "FOOD Class" << endl; }
virtual void printPrice() { cout << this->price << endl; }
void printLine() { cout << "=================" << endl; }
};
class SNACK : public FOOD
{
private:
int price = 1000;
public:
SNACK() { printf("SNACK created\n"); }
~SNACK() { printf("SNACK deleted\n"); }
/* override 시 compile error */
void printName(int value) { cout << "SNACK Class, value : " << value << endl; }
void printPrice() { cout << this->price << endl; }
/* override 시 compile error */
void printLine() { cout << "------------------------" << endl; }
};
class MILK : public FOOD
{
private:
int price = 500;
public:
MILK() { printf("MILK created\n"); }
~MILK() { printf("MILK deleted\n"); }
void printName() { cout << "MILK Class" << endl; }
void printPrice() { cout << this->price << endl; }
};
int main(void)
{
FOOD* foodList[3];
foodList[0] = new FOOD();
foodList[1] = new MILK();
foodList[2] = new SNACK();
printf("\n---- TEST START ----\n\n");
for (int i = 0; i < 3; i++)
{
foodList[i]->printName();
foodList[i]->printPrice();
foodList[i]->printLine();
putchar('\n');
}
// FOOD type의 SNACK 객체
//foodList[2]->printPrice(5); // compile error
for (int i = 0; i < 3; i++) delete foodList[i];
printf("\n\n---- TEST END ----\n\n");
SNACK* snack = new SNACK();
//snack->printName(); // compile error
snack->printName(5);
snack->printLine();
return 0;
}
void printName(int value) 으로 잘못 상속하였기 때문에 FOOD type의 SNACK에서 FOOD Class가 출력되었고,
SNACK type의 SNACK에서는 SNACK Class, value : 5가 출력되었다.
따라서 override 키워드를 이용하면 virtual 함수의 overriding을 컴파일 타임에 제대로 확인할 수 있다.
반응형
'개발 > C, C++' 카테고리의 다른 글
C++ 스마트 포인터 (Smart Pointer) (0) | 2021.10.03 |
---|---|
C++ - 형변환 연산자 (casting operators) (0) | 2021.08.26 |
C++ - 가상 소멸자 (Virtual Destructor) (0) | 2021.08.23 |
C++ - explicit 키워드 (0) | 2021.08.22 |
C++ - virtual, type casting (0) | 2021.08.15 |
댓글