안녕하세요 틴구입니다.
"오늘 올릴 내용은 뭐냐 class 상속에 대한 기초 개념과 이론입니다."
1.클래스 상속
클래스 상속이란
기존에 있는 클래스의 멤버 변수와 멤버 함수를 물려받아 새로운 클래스를 작성하는 것을 의미합니다.클래스는 부모의 or 자식의 관계를 형성할 수 있습니다.
상속관계에서의 생성자와 소멸자 호출 순서
생성자 : 부모 -> 자식
소멸자 : 자식 -> 부모
ex)
위의 코드처럼 구성을 하였을 경우 호출 순서에 의해 아래처럼 출력이 됩니다.
클래스 상속의 장점
기존의 클래스를 재활용할 수 있습니다.즉 부모클래스에 공통으로 가져야 할 멤버변수를 선언하고 공통으로 가져야 할 기능을 멤버함수로 만들어준
후에 개별적인 내용들만 자식클래스에 따로 조금씩 만들어서 하나의 객체를 만들때 사용합니다.
다형성
다형성 : 상속관계에 있는 클래스들은 서로 형변환이 가능하다. 다양한 부모와 자식 타입으로의 형변환을
지원해주기 때문에 같은 부모를 상속받고 있는 자식클래스는 해당 부모타입으로 모든 자식클래스 타입의
변수들을 부모타입으로 관리가 가능해지게 되는 것이다.
CChild 클래스를 동적할당하고 해당 메모리 주소를 CParent 포인터 타입에 저장해두었다.
서로 상속관계에 있는 클래스이기 때문에 이런 형변환이 가능한 것입니다.
단 private 상속을 한 클래스의 경우는 접근이 불가능하하여 형변환이 불가능하다.
그런데 위의 코드를 출력하게 되면
생성자는 부모 -> 자식 순으로 잘 출력이 되는데 소멸자의 경우는 CParent의 소멸자만 호출이 되고 있습니다.
이게 뭐가 문제냐면 위의 main함수에서 동적할당을 하고 뒤에 delete를 하는것은 상관이 없습니다
그런데 자식 클래스에서 멤버 변수를 만들고 생성자에서 동적할당을 해주게 된다면
소멸자가 호출이 안되어서 못지우게 되고 메모리 릭이 남게됩니다.
이 방법을 해결하기위해 virtual이라는 가상 함수를 이용하여 해결해야 합니다.
가상함수란
가상함수 : 함수 앞에 virtual을 붙여서 가상함수로 만들어줄 수 있다.
가상함수를 가지고 있는 클래스를 이용해서 객체를 생성하면 가상함수 테이블의 주소를 가지고 있는
포인터 변수를 내부적으로 가지게 된다.
가상함수 테이블은 해당 클래스가 가지고 있는 가상함수의 함수주소를 저장하고 있는 배열이라고 볼 수 있다.
클래스를 이용해서 객체를 생성하면 내부에 __vfptr 포인터 변수가 만들어지고 이 변수에 가상함수테이블
배열의 메모리 시작주소가 들어가게 된다.
virtual 사용법
부모노드의 소멸자에 앞에 virtual 달아준다virtual을 붙여주게 되면
정상적으로 자식클래스의 소멸자가 출력이 되는것을 확인할 수 있다.
함수 오버라이딩
함수 오버라이딩이란 가상함수를 이용하여 자식클래스에서 해당 함수를 재정의 하는것을 뜻합니다.
함수를 재정의 할때는 반환타입, 함수 이름, 인자가 모두 동일해야 합니다.
부모클래스에 virtual void Output함수를 만들고
자식 클래스에서 부모클래스에서 사용한 똑같은 반환타입, 같은 함수 이름, 같은 인자를 사용하여
재정의를 하고 새로운 child1의 클래스를 만들고 CParnt클래스를 public 상속하고
아래의 코드처럼 출력을 하게되면
이렇게 코드가 출력이 됩니다.
child 의 경우는 Output함수를 재정의를 하여 나는 CChild 입니다 가 출력이 된 것이고
child1의 경우는 재정의를 하지 않아서 나는 CParent 입니다 가 출력이 된 것입니다.
재정의 개념
일반 멤버함수에 virtual을 붙여서 가상함수로 만들어주면 자식클래스의 재정의를 해도 되고 안해도 된다.
만약 CChild클래스는 재정의가 되어있고 CChild1 클래스는 재정의가 안되었을 경우
가상함수 테이블에 저장되는 함수의 주소는 CChild 클래스를 이용해서 생성한 객체는 CChild클래스에
재정의한 함수의 주소가 들어가게 되고
CChild1 클래스를 이용해서 생성한 객체는 재정의가 안되어 있으므로 CParent 클래스에 정의된 함수의
주소가 들어가게 되는 것이다.
그래서 가상함수를 호출을 하게 되면 먼저 가상함수인지를 판단하고 가상함수라면 가상함수 테이블에서
실제 함수의 주소를 찾아온 후에 해당 함수의 주소를 이용하여 함수호출을 진행하게 되므로
CChild 클래스를 이용해서 생성한 객체는 가상함수테이블에 CChild클래스에 재정의된 함수의 주소가 들어가
있으므로 재정의된 함수를 호출해주고
CChild1 클래스를 이용해서 생성한 객체는 가상함수테이블에 CParent클래스에 선언된 함수의 주소가
들어가 있으므로 해당 함수를 호출하게 되는 것이다.
'c++' 카테고리의 다른 글
20210813 파일 입출력 (0) | 2021.08.14 |
---|---|
20210726~28 class TextRPG (0) | 2021.07.29 |
20210723 사용자 정의 헤더 파일 ~ Template (0) | 2021.07.25 |
20210722 객체 지향 프로그래밍 ~ static멤버함수,싱글톤 (0) | 2021.07.23 |
20210721 함수 ~ 오퍼레이 (0) | 2021.07.21 |
댓글