다음 세 부분을 어떻게 설명할지 고민이다.
1. 오버라이딩
2. 가상 함수
3. 형변환
이 글에서는 오버라이딩을 먼저 설명해보겠다.
자식 클래스에서는 부모 클래스에서 선언된 것과 동일한 이름의 멤버를 사용할 수 있다.
1 2 3 4 5 6 7 8 9 | class Base { public: int a = 1; }; class Derived : public Base { public: int a = 2; }; | cs |
이렇게 써도 에러가 나지 않는다.
그럼 Base와 Derived 타입의 객체를 만들어 a 멤버변수를 출력해보자.
1 2 3 4 5 6 7 | int main() { Base b; Derived d; cout << b.a << endl; cout << d.a << endl; } | cs |
<출력 결과>
1
2
b.a는 1이 출력되는 것이 당연하다.
d.a는 2가 출력되었다. 즉 Base의 a가 아닌 Derived에 있는 a가 출력되었다고 볼 수 있다.
여기서 짚고 넘어가야 할 것은, Derived 클래스에는 실제로 두 개의 멤버변수가 있다는 것이다.
Base의 a를 상속받고, 고유의 a를 또 하나 더 가지고 있는 상태이다. 그러나 d.a라고 하면 Derived 클래스에 정의된 a만 접근 가능하다.
그 이유가 바로 Derived 클래스의 a가 Base 클래스의 a보다 우선하기(override) 때문이다.
이것을 오버라이딩이라 한다.
당연히 그렇다고 해서 Base에 있는 a를 접근할 수 없는 것은 아니다.
예전 강좌에서 클래스 이름은 네임스페이스의 기능도 한다고 얘기한 적이 있다.
즉 네임스페이스 표시(::)를 통해 명시적으로 Base에서 선언된 멤버라는 것을 알려주면 된다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | class Base { public: int a = 1; }; class Derived : public Base { public: int a = 2; }; int main() { Base b; Derived d; cout << d.a << endl; cout << d.Base::a << endl; cout << d.Derived::a << endl; } | cs |
<출력 결과>
2
1
2
변수뿐만 아니라 함수도 오버라이딩할 수 있다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | class Base { public: void Print() { cout << "Base" << endl; } }; class Derived : public Base { public: void Print() { cout << "Derived" << endl; } }; int main() { Base b; Derived d; d.Print(); d.Base::Print(); d.Derived::Print(); } |
<출력 결과>
Derived
Base
Derived
변수의 오버라이딩을 잘 이해했다면 설명이 필요없는 부분이다.
오버라이딩이 중요해지는 것은 포인터를 사용하면서부터이다.
그보다 먼저 알아야 할 내용이 있다.
1 2 | int a = 10; char *c = &a; | cs |
에러가 난다.
char타입의 포인터는 char타입의 변수만 가리킬 수 있기 때문이다.
그런데 다음 코드를 보자.
(Derived는 아까처럼 Base를 상속받은 클래스라고 가정한다.)
1 2 | Derived d; Base *b = &d; | cs |
에러가 나지 않는다!
일반화해서 말하면,
부모를 가리키는 포인터는 자식도 가리킬 수 있다.
두 클래스가 int와 char처럼 완전히 남남 관계는 아니라는 건 알지만, 그래도 신기하다.
물론 Derived 포인터로 Base 객체를 가리키는 건 에러가 난다.
"이게 왜 문법적으로 오류가 없는가?"
사실은 C++를 만든 사람들 마음이다. 원래는 다른 타입끼리는 포인터 참조가 불가한데, 부모-자식 관계에서는 허용할 만한 이유가 있는 것이다.
다시 말해 "이 기능을 왜 만들었는가?"에 대해 생각해보자.
힘들다. 다음번에 이어서 적겠다.
'강좌연구' 카테고리의 다른 글
[C++ 강좌연구] 동적 바인딩 (0) | 2019.06.18 |
---|---|
[C++ 강좌연구] 정적 바인딩 (0) | 2019.02.02 |
댓글