오늘까지가 중간고사 범위
fuction overriding
부모 클래스의 함수를 자식 클래스가 오버라이딩 한다.
스태틱 디스패치와 다이나믹 디스패치
스태틱이라는 것은 컴파일 타임이 시작 전인 것이다. 어떤 함수를 사용할 것인지 컴파일러가 정해준다.
컴파일러가 아는 것은 타입밖에 모른다.
스태틱 캐스트. 캐스트를 사용하면 우리가 원하는 클래스의 함수를 불러올 수 있도록 한다.
Developer 타입을 확인하고 Developer 타입의 함수를 호출하게 된다.
다이나믹 캐스트를 이용하자. Employee를 따라가서 Developer를 찾고, 각각의 함수가 원하는 함수로 발동되게 된다.
실습 때 한 게 이것이다.
만약에 디벨로퍼 리서쳐 말고 다른 하나의 타입을 클래스를 추가하고, 그 타입도 임플로이를 상속받는 것이라면 또 반복해야한다.
if-else문을 만들고 다시 또 구현해야하면 너무 귀찮다.
C++은 스태틱이 기본이지만, 다이나믹도 지원한다. virtual이라는 키워드를 사용하면 다이나믹 디스패치를 사용할 수 있는 것이다. 컴파일러가 미리 정해주지 않고, 리시브 오브젝트를 확인하고 그 오브젝트에 해당하는 함수를 불러준다.(실행하다가!) 객체를 보고 결정해주는 것이 다이나믹 디스패치이다.
Runtime overhead가 발생하지만 되게 표현혁은 높아진다. 굳이
다만, 해당 변수의 타입이 포인터이거나 레퍼런스여야 한다.
virtual function은 앞에 버츄얼이라는 것을 붙여준다. 상속했을 때, 소멸할 때 버츄얼을 붙였었다.
함수 앞에 버츄얼을 두면 버츄얼 펑션이 된다. 이 함수를 호출하는 것은 다이나믹 디스패치가 되는 것이다. 어떤 함수가 불릴지는 실행 시점에 계산을 하게 되는 것이다.
아래에서는 코드가 그렇게 바뀐 것 없이 버츄얼 코드만 추가된 것이다.
부모클래스의 버추얼로 정의된 함수를 불렀을 때, 자동으로 버츄얼로 작동하게 된다. 버츄얼이라는 키워드를 붙이지 않아도 부모 클래스에 적혀있기 때문에 바로 버츄얼로 된다.
베이스 클래스의 함수가 버추얼로 되어있다면 디라이브드 클래스의 함수도 버추얼로 함수가 정의된다. 이렇게 되면 코드를 깔끔하게 작성할 수 있게 된다.
버추얼만 붙이면 다이나믹 디스패치가 실행된다!
다이나믹 디스패치가 동작하기 위해서는 포인터나 레퍼런스 타입이어야 한다.
A a;라는 클래스에 대해서 예제를 들며 설명했음.
자식 클래스는 상속받았다. 자바에서는 @override 를 알려주었다. 이거 없어도 아무 상관은 없다. C++도 마찬가지이다. 어노테이션으로 컴파일러가 버그를 체크할 때만 사용하게 되는 것이다.
C++에서는 foo() override;라고 써서 오버라이드를 알려준다. 물론 있으나 없으나 실행에는 지장없지만 쓰기를 권장함.
- 부모 클래스의 함수를 재정의한 것이라는 것을 명확하게 알려줄 수 있다.
- 컴파일러에게 도움이 된다. 우리가 뭔가 잘못했을 때 컴파일러에게 도움을 받을 수 있다. 나도 모르게 함수 이름을 잘못 썼을 때, foo()를 오버라이드 할려 했는데 too() 라고 해버렸을 때. 검사해서 알려준다.
- foo()를 상속받았는데 foo(int x)를 사용했을 때는 인자를 받은 함수는 다른 함수라고 생각하겠지만 override를 붙여주면 이게 상속받은 함수가 맞는지 나의 의도를 확인해줄 수 있다. 에러를 통해서!
- 컴파일러에게 결함을 잡도록 힌트를 준다.
실수를 방지하기 위해서 override 키워드를 사용하는 것이 좋다.
실행 시점에 모든 변수가 어떤 객체를 실제로 어떻게 가리키고 있는지 확인하는 것은 너무나도 Cost가 크다.
RTTI 를 사용하면 객체의 모든 변수를 확인하니까 비용이 너무 크다. 다른 방법으로 지원하는데 VPTR을 지원한다. 모든 객체는 버추얼 포인터가 있고, 버추얼 테이블이 있다. 자기 자신 클래스의 테이블을 가리키는 VPTR
vptr은 각 클래스의 VTABLE을 가리킨다.
훨씬 가볍게 할 수 있다. (모든 객체의 변수를 확인하지 않는다!)
상속받을 때 컴파일러가 테이블의 인덱스를 계산해서 상속받은 함수끼리는 같은 인덱스에 테이블을 놓을 수 있도록 한다.
C++에서 abstract class 만드는 법.
자바에서는 앱스트랙트 키워드를 썼지만, C++에서는 = 0;을 바디 {} 대신에 쓴다. 큐어 버추얼 펑션이라고 한다 이것을.
실체가 몸체가 없는 것.
상속할 때만 사용할 수 있다. 상속을 받았는데 퓨어 버추얼 펑션이 있는데 오버라이드로 정의하지 않으면 나도 앱스트랙트가 된다. 내가 앱스트랙트가 되지 않으려면 오버라이드로 다시 정의를 해주면 된다.
상속받은 클래스가 오버라이드로 정의를 해야만 앱스트랙트에서 벗어나게 된다.
상속할 때 기존의 것과 조금의 다른 기능을 만들고 싶을 때 하는 것이다. 객체를 확장해서 정의할 수 있다.
Function overloadin and overriding 을 잘 보아야 한다.
버추얼 펑션이 하나라도 있으면 폴리모르픽 클래스이다. 소멸자에 버추얼을 붙여준다.
퓨어 버추얼일 필요는 없다. 버추얼 아무거나 하나 있으면 폴리몰픽 클래스이다.
일반적으로 상속을 할 때, 부모클래스가 폴리몰픽 클래스 여야만 뭔가 생길 수 있는 오류들을 방지할 수 있다.
첫 번째는 다이나믹 디스패치는 부모클래스가 폴리몰픽 클래스가 아니면 실행되지 않는다.
소멸자에 버추얼을 붙이는 것에 대해서.
소멸자는 지금 동적으로 할당된 메모리를 해제해준다.
문제가 있다. 어떤 문제인가.
일반적으로 함수에 버추얼이 안 붙어있으면 컴파일러가 재분류를 해준다. 소멸자도 마찬가지이다. 소멸자는 여기서 스태틱 디스패치를 하게된다. 여기서 딜리트를 했을 때, 소멸자가 스태틱 디스패치를 한다. 현재 employee의 클래스는 Employee인데 그러면 저기에 소멸자를 부르는데, 실제 객체는 Developoer로 선언되어서 Developer에 할당되어 있는 메모리를 해제하지 않는다. 따라서 메모리 누수가 발생하게 된다.
그래서 소멸자에 버추얼을 붙여준다. 다이나믹 디스패치가 되어서 실제로 가리키는 객체는 디벨로퍼인 것을 확인하고 디벨로퍼의 소멸자를 부르게 된다.
소멸자에서 메모리 해제를 하거나 정해진 일을 해야만 하고, 상속받는다면 소멸자를 버추얼로 해주어야 이러한 불상사를 방지할 수 있다.
버추얼 안 붙였을 때 오류가 안 뜰 수 있으니까 주의를 해주자.
에러와 워닝의 차이 : 개발자의 실수가 명확해! "너 이거 고쳐!" 에러, 개발자가 의도가 뭔가 있나? "너 이거 괜찮은지 확인해봐!" 워닝
자바에서는 멀티 인헤리턴스를 받아들이지 않는다. 부모가 한 명이어야만 해! 그 외 여러 프로그래밍 언어는 그렇지 않을 수 있다. 자식이 부모를 여러 명 갖는 것을 허용해준다.
소멸자 부를 때, Developer "나"를 지우고! 그 뒤에서 순서대로 Employee->Citizen 순으로 지워준다. 부를 때는 첫 번째 꺼 부르고, 두 번째 꺼 부르지만, 소멸자는 이것의 역순. 생성-소멸은 서로 역순으로 진행된다.
자바에서는 왜 이걸 지원하지 않는가? 다이아몬드 프라블럼이 발생한다. 이게 문제가 부모 A의 문제인지 부모 B의 문제인지 잘 모른다. 어디서 상속받은 게 문제인 건지 모른다.
꼭 멤버 필드가 아닌 멤버 함수라도 이런 문제가 발생할 수 있다. 동일 함수, 변수를 가지고 있으면 어떤 게 문제인지 선택의 기로에 서게 되는데 컴퓨터는 결정을 못 한다.
10페이지 중간고사
문제는 15개 정도이고, 세부 문제가 있다. 어떤 식으로 문제가 나오냐. 코드가 엄청나게 많고, 코드를 해석할 수 있으면 풀 수 있다. 손코딩은 없다. 코드를 해석할 수 있으면 다 풀 수 있고 거기에 몇 가지 개념을 알고 있으면 충분히 다 풀 수 있다.
시험 시간 연장. 매년 문제가 다르고, 난이도는 비슷하고 30분 안에 다 풀었는지는 모르지만 나가는 친구들도 있다. 키워드의 개념을 물어보는 것이 있는가? 너무 어려운 내용은 담지 않았다. 대략적인 내용을 알고 있다면 한다.
펜/ 학생증이 있어야 한다. 펜 꼭 갖고와야 한다. 연필이든 볼펜이든 상관 없고 부분점수는 굉장히 열심히 준다. 물론 성에 안 찰 수도 있다.
'[Computer Science] -보호글 > [객체지향설계]' 카테고리의 다른 글
[객체지향설계] 10/31 이론 -Design Pattern (0) | 2023.10.31 |
---|---|
[객체지향설계] 10/03 이론 (0) | 2023.10.23 |
[객체지향설계] 09/26 이론 (0) | 2023.09.26 |
[객체지향설계] 9/19 이론 (0) | 2023.09.19 |
[객체지향설계] 9/12(화) 이론 (0) | 2023.09.12 |