상속이 필요한이유
프로그램을 코딩할때 , 보통 데이터가 묶여있는 클래스와 그 데이터를 이용하여 기능의 처리를담당하는 클래스를 따로 작성하는데 , 이때 기능의 처리를 담당하는 클래스를 컨트롤 ( control ) 클래스 혹은 핸들러 ( handler ) 클래스라고한다. 이때 데이터가 묶여있는 클래스에 새로운 멤버가 생기는등의 변경사항이 있을때 , 컨트롤클래스의 수정이 불가피해지며 , 그 결과 클래스를 전부 수정해야하는 경우가 생긴다. 이러한 불편을 줄이기위해서 소프트설계에있어서 중요시하는것은 " 요구사항의 변경에 따른 프로그램의 유연성 " , " 기능의 추가에따른 프로그램의 확장성 " 이다. 이를위하여 상속의 개념이 도입되었다.
상속이란
B 클래스가 A 클래스를 상속한다면, B 클래스는 A가 가지고있는 모든 멤버를 물려받게된다. 이때 public 상속이냐 , private 상속이냐 , protect 상속이냐에 따라 멤버의 접근권한이 달라진다.
세가지 형태의 상속
class UnivStudent : public Person // public 상속 : Person의 멤버중 Public보다 접근의 범위가 넓은 멤버는 public으로 변경시켜서 상속 ( 그대로 상속 )
class UnivStudnet : private Person // private 상속 : Person 의 멤버중 private 보다 접근의 범위가 넓은 멤버는 private로 변경시켜서 상속 ( Person의 모든멤버를 Private 접근권한으로 상속 )
class UnivStudnet : protected Person // protect 상속 : Person 의 멤버중 protect 보다 접근의 범위가 넓은 멤버는 protceted로 변경시켜서 상속 ( Person의 public멤버를 protected 접근권한으로 상속 )
거의 대부분의 상속은 public 상속으로 이루어진다
protected 로 선언된 멤버가 허용하는 접근범위
protected 로 선언된 멤버변수는 이를 상속하는 유도클래스에서 접근이 가능하다. 이 키워드를 이용하면 유도클래스에게만 제한적으로 접근을 허용하여 유용하게 사용될 수 있지만, 기본적으로는 기초 클래스와 이를 상속하는 유도클래스 사이에서도 정보은닉이 지켜지는것이 좋다.
상속을 위한 조건
상속을 위한 기본조건인 IS - A 관계
ex )
무선전화기 is a 전화기
노트북컴퓨터 is a 컴퓨터
위와같이 상속관계로 묶고자하는 두 클래스가 IS - A 관계로 표현되지 않는다면 적절한상속의 관계가 아닐확률이 높다.
HAS - A 관계도 상속의 조건은되지만 복합관계로 이를 대신하는것이 일반적이다.
ex)
경찰 has a 총
위와같이 소유의 관계를 상속으로 ( 총클래스를 경찰클래스가 상속 ) 해결할 수도 있지만, 이때 경찰이 곤봉을 든다고 가정했을때 , 클래스의 수정이 어려워진다. 따라서 이런경우는 상속이외의 다른방법으로 해결하는것이 좋다.
위 두 상황을 제외하면 , 상속이 형성될 상황은 없다고봐도 무방하다.
상속의 방법
include<iostream>
include<cstring>
using namespace std;
class Person
{
private :
int age;
char name[50];
public :
Person(int myage , char* myname) : age(myage)
{
strcpy(name,myname);
}
void WhatYourName() const
{
cout << "My name is : " <<name<<endl;
}
void HowOldAreYou() const
{
cout << My age : " << age << endl;
}
};
class UnivStudent : public Person // Person 클래스를 public 으로 상속
{
private :
char major[50]
public :
UnivStudent(char * myname , int myage, char * mymajor) : Person(myage,myname) // 이니셜라이저의 형태로 Person생성자 호출
{
strcpy(major,mymajor);
}
void WhoAreYou()
{
WhatYourName();
HowOldAreYou();
cout << "My major : "<<major <<endl;
}
};
int main (void)
{
UnivStudent ustd1("LEE",22,"Computer eng."); // UnivStudent클래스와 Person 클래스의 생성자 둘다호출 , 초기화
ustd1.WhoAreYou();
return 0;
}
이때 , 기초클래스인 Person의 private 멤버에는 유도클래스인 UnivStudent 에서도 접근이 제한된다. 이는 접근제한의 기준이 객체가아닌 클래스이기때문이다. 따라서 Person에 정의된 Public 함수를 이용해 Person의 private 멤버에 접근해야한다 . 정보의 은닉은 객체내에서도 진행된다.
유도클래스의 객체 생성과정
유도클래스의 객체생성에서 기초클래스의 생성자는 100% 호출되며 , 유도클래스의 생성자에서 기초클래스의 생성자 호출을 명시하지않으면 기초클래스의 void 생성자가 호출된다.
-> 기초클래스의 생성자와 유도클래스의 생성자는 반드시 모두 호출된다 -> 클래스의 멤버는 해당 클래스의 생성자를 통해서 초기화해야한다.
생성자의 호출은 기초클래스 -> 유도클래스 순으로 호출되며, 소멸자의 호출은 그 반대인 유도클래스 -> 기초클래스의 순으로 진행된다.
-> 소멸자 또한 기초클래스와 유도클래스 모두 호출된다 -> 만약 생성자에서 동적할당한 멤버가 있다면 , 그 메모리공간은 각 클래스의 소멸자에서 해제해야한다.
ex)
class Person
{
private :
char * name;
public :
Person ( char * myname);
{
name = new char[strlen(myname)+1]; // 동적할당
strcpy(name,myname);
}
~Person ()
{
delete[] name; // 해당클래스에서 메모리해제
}
};
'C++언어 > 열혈C++' 카테고리의 다른 글
C++ : Chapter-9 가상의 원리와 다중상속 (0) | 2018.05.24 |
---|---|
C++ : Chapter -8 상속과 다형성 (0) | 2018.05.22 |
C++ : Chpater -6 friend , static 그리고 const (1) | 2018.05.16 |
C++ : Chapter -5 복사생성자 (0) | 2018.05.10 |
C++ : Chapter -4 클래스 PART2 (0) | 2018.05.02 |