상속이란?
현실의 금수저가 부모에게 많은 재산을 물려받아 금방 안정된 생활을 누릴 수 있고, 이에 비해 흙수저는 물려받은 것이
거의 없어 모든 것을 자신이 노력해서 얻어야 합니다.
상속도 이와 비슷한 개념입니다.
기존에 어떤 클래스가 잘 만들어져 있으면 이를 상속받아 새로운 클래스를 만드는 것입니다.
이때, 상속을 해준 클래스를 부모(parent), 슈퍼(super), 기반(base) 클래스라고 합니다.
상속받아서 만든 새로운 클래스는 자식(child), 서브(sub), 파생(derived) 클래스라고 합니다.
만약 , 부모 클래스가 많은 기능을 갖고 있다면 이를 상속한 자식들은 많은 코드를 넣지 않아도 금방 강력한 기능을 가진
클래스가 됩니다. 금수저 클래스입니다.
이와 반대로 부모 클래스가 빈약하고, 자신에게 필요한 많은 기능이 구현되어 있지 않다면 자식 클래스에서 많은 코드를
고생해서 구현해야 합니다. 흙수저 클래스입니다.
금수저 흙수저는 비유를 위해 지어낸 것이므로 쓰시면 안 됩니다.
현실에서는 부모가 자식에게 재산을 상속하면 부모는 전부나 일부를 그만큼 잃는 것이지만
프로그래밍에서의 상속은 부모가 자식에게 상속하면 부모가 가진 전부를 자식에게 주게 되고 줘도 부모에 상속된 멤버가 없어지는 것은 아닙니다.
또한, 여러 자식에게 자신의 전부를 동일하게 나눠줄 수 있습니다.
파생 클래스
상속(inheritance)은 기존에 잘 동작하는 클래스를 확장하여 새로운 파생 클래스를 만드는 방법입니다.
상속을 이용하여 새로운 클래스를 정의하는 방법은 아래와 같습니다.
class 파생클래스명 : public 기반클래스명
{
// 새로운 특징들 (새로운 멤버 변수 또는 멤버 함수)
// 멤버의 재정의 (부모의 멤버 변수나 멤버 함수를 자식 클래스에서 다시 정의하는 것)
// !주의: 하지만 되도록 부모의 멤버 변수를 개발자를 혼란스럽게 할 가능성이 많기 때문에
// 사용 안하는걸 추천한다
// 보통은 멤버 함수를 재정의 함
}
- 문자 ' : '는 상속을 나타낸다
- ' : ' 다음의 public은 private나 protected가 될 수도 있다.
- 대부분 public을 사용하므로 이 부분을 빠트리지 않도록 조샘해야 합니다.
- 만약 이 부분을 빠뜨린다면 private으로 인식하여 부모가 public이나 protected로 선언한 부분도
- private 멤버가 되어 자식은 절대로 이용할 수가 없습니다.
- 그러면 상속을 쓰는 이유가 사라집니다
- 그러므로 public을 그냥 씁시다.
- 파생 클래스에는 기반 클래스의 모든 멤버가 포함됩니다.
- 파생 클래스도 다른 클래스의 기반 클래스가 될 수 있습니다.
- 하나의 클래스는 여러 클래스로 상속될 수 있습니다.
자식 클래스의 크기는?
자식 클래스의 크기 = 부모 클래스의 멤버 변수의 크기 + 자식 클래스의 멤버 변수의 크기 입니다.
언제 상속을 사용할까?
자식 클새의와 부모 클래스간에 "is a" 또는 "is a kind of"의 관계가 있는 경우 상속을 사용합니다.
왜 갑자기 영어가 나오는지 당황할 수 있습니다. 그럼 예를 보며 설명하겠습니다.
- "포유류"는 "동물"의 일종(is a kind of)
- "트럭"은 "자동차"의 일종(is a kind of)
- "배"는 "탈 것"의 일종(is a kind of)
- "좀비"는 "괴물"의 일종(is a kind of)
이런 식으로 큰 개념에서 작은 개념으로 가는 방향으로 가면 상속을 쓰기에 자연스럽습니다.
class Monster
{
public:
int x, y; //몬스터의 위치
int size; //몬스터의 크기
string str; //몬스터의 모양
Monster(int mx = 0,int my = 0, int msize = 0, string mstr = ">0<")
: x(mx), y(my), size(msize), str(mstr) {}
}
class Jombi : public Monster
{
bool vertical; //좀비의 이동 방향 , 새로운 멤버 변수
//상속으로 부모의 멤버 변수를 받아 좀비만의 생성자 생성
Jombi(int mx = 3,int my = 3, int msize = 30, string mstr = "xOx", bool jvertical = false)
: Monster(mx, my, msize, mstr), vertical(jvertical) {}
}
하지만, 클래스들 사이에 "has a" 관계가 있다면 상속은 자연스럽지 않습니다.
이런 관계는 "포함"으로 처리하는 것이 바람직합니다.
- "자동차"는 "바퀴"를 가지고 있다
- "자동차"는 "주인"가 있다(가지고 있다)
- "선분"는 "2개의 점"을 가지고 있다
- "원"은 중심을 나타내는 "점"을 가지고 있다
class Point
{
int x, y;
}
class Line
{
Point p1, p2; //점 두개의 객체를 가진다
}
멤버 함수의 재정의
간단하게 부모에게 멤버 함수를 상속 받았지만 자식에게는 맞지 않아 다시 재정의 하는것을 말합니다..
예로 포유류 클래스가 있고 새끼를 낳는 멤버 함수 breeding()가 있다. 그것을 포유류에 속하는 오리너구리가 상속받지만
오리너구리는 알을 낳기 때문에 상속된 멤버 함수를 그냥 쓰기엔 문제가 있습니다.
그렇기 때문에, 재정의(overriding)을 통해 오리너구리 클래스는 breedig()의 내용을 알을 낳는것으로 바꾸면 됩니다.
다른 포유류의 특징을 가진 멤버 함수들은 그대로 사용하면 됩니다.
만약 부모 클래스의 멤버 함수와 이름은 같지만 매개변수가 다른 경우는 어떻게 될까?
이것은 재정의가 아니다. 자식 클래스에 새로운 멤버 함수를 추가한 것입니다.
멤버 함수의 호출 순서
이건 3줄 요약이 가능합니다.
- 먼저 그 클래스에 멤버 함수가 있는지를 찾는다.
- 만약 없으면 찾을 때 까지 계속 부모 클래스로 올라간다.
- 만약 어떤 부모 클래스에도 없다면 마지막으로 전역함수에서 찾는다.
만약 전역함수에도 없다면 오류를 발생합니다.
다중상속
다중 상속(multiple inheritance)은 하나의 클래스가 여러 부모 클래스로부터 직접 상속 받는 것을 말합니다.
class 자식클래스명 : public 부모클래스1, 부모클래스2
{
// 자식 클래스에서 추가된 멤버들
}
그러나 다중 상속은 잠재적인 문제가 있어 가능한 사용하지 않는 것이 바람직합니다.
만약 오리너구리가 오리와 너구나 두개의 부모 클래스를 상속 받고 오리와 너구이 모두에 구현된
move라는 멤버 함수를 호출하면 컴파일러는 누구의 함수를 호출할건지 결정할 수 없습니다.
따라서 컴파일 오류가 발생합니다.
'C++ 프로그래밍 > 클래스' 카테고리의 다른 글
다형성-다형성이란? (0) | 2022.08.12 |
---|---|
다형성-상속에서의 형 변환 (0) | 2022.08.12 |
.과 ->의 쓰는 용도 (0) | 2022.08.04 |
함수의 설계와 객체의 복사 (0) | 2022.07.28 |
얕은 복사와 깊은 복사 (0) | 2022.07.28 |