1. Employee problem
소스 자체는 문제가 없으나 요구사항이 많아질경우 클래스전체를 뜯어 고쳐야 하는 경우가 발생할경우가 있다..그걸 막기 위해 우리는 지금 부터 상속을 배운닷!!!
2. 상속의 기본개념
class Person{
int age;
char name[20];
public:
int GetAge() const{
return age;
}
const char* GetName() const{
return name;
}
Person(int _age=1,char* _name="noname"){
age=_age;
strcpy(name,_name);
}
};
class Student: public Person{
char major[20];
public:
Student(char* _major){
strcpy(major,_major);
}
const char* GetMajor() const{
return major;
}
void ShowData() const{
cout<<"이름 : "<<GetName()<<endl;
cout<<"나이 : "<<GetAge()<<endl;
cout<<"전공 : "<<GetMajor()<<endl;
}
};
{
Student Kim("computer");
Kim.ShowData();
};
위의 예제의 경우 Student 클래스가 Person클래스를 public 상속한다.
여기서 상속되는 클래스는 Base클래스, 상속하는 클래스는 Derived 클래스라고 한다.
일단 Student 클래스가 Person클래스를 생성하면 이런 메모리공간이 할당된다.
상속한 클래스Student 는 상속된 Person의 멤버들도 포함시킨다는 것이다.이게 상속의 기본원리 이다.
3. 상속하는 클래스의 객체 생성 및 소멸과정
간단한 예를 하나 들어보자.
public:
AAA(){
cout<<"AAA()호출"<<endl;
}
AAA(int i){
cout<<"AAA(int i)호출"<<endl;
}
};
public:
BBB(){
cout<<"BBB()호출"<<endl;
}
BBB(int j){
cout<<"BBB(int j)호출"<<endl;
}
};
int main()
{
cout<<"객체1생성"<<endl;
BBB bbb1;
BBB bbb(10);
};
이런 코드가 있다. 일단 실행결과를 보고 말하자.
1. 메모리공간 할당. 상속되는 클래스를 감안하여 메모리 할당
2. Base클래스의 생성자 실행
3. Deriver클래스의 생성자 실행
아무것도 전달 안해주고 있지..그럼 void생성자가 호출이 된다..클래스 BBB의 void생성자로 가보니..어라..Person클래스를 상속하고 있네? 그럼 몸체를 실행하기전에 AAA클래스로간다.
자..가보니 AAA클래스에 생성자가 2개나 있다..하나는 void생성자 하나는 int i를 받을수 있는 생성자..상식적으로 뭐가 호출되겠냐? 그래 void생성자가 호출이되고 실행이 되.그다음에
아까 호출만한 BBB클래스의 void생성자를 실행하지.. 그담에 또 BBB클래스의 bbb2객체를 만들면서 이번엔 인자값으로 10을 주고 있어..10을 받을수 있는 BBB클래스의 생성자를 찾아보자..있다..2번째 그걸 호출하고 몸체를 실행하려고 봤더니..또 상속하고있네..ㅅㅂ..
그럼 다시 AAA클래스로 올라가서...이번엔 어떤 생성자를 호출,실행 해야될까..이번에도
void생성자를 호출한다.자세한 설명은 좀 있다가 하고..그담에 실행후 다시 BBB클래스로 와서 나머지 부분 실행하고 종료한다..그래서 나온 결과값이 저위에 값..휴.
만약에 저 위에서 bbb1객체를 생성하면서 상속되는 클래스의 두번째 생성자.(int i)를 인자로 받는 생성자를 호출하고 싶다면..우리가 전에 배운 멤버 이니셜라이져를 써먹으면 된다.
cout<<"BBB()호출"<<endl;
}
j를 인자로 받을수 있는 AAA클래스의 생성자를 호출하라..라는 뜻이 된다.
객체 생성과정의 적용
int age;
char name[20];
public:
int GetAge() const{
return age;
}
const char* GetName() const{
return name;
}
Person(int _age=1,char* _name="noname"){
age=_age;
strcpy(name,_name);
}
};
char major[20];
public:
Student(int _age,char* _name,char* _major){
age=_age;
strcpy(name,_name);
strcpy(major,_major);
}
const char* GetMajor() const{
return major;
}
void ShowData() const{
cout<<"이름 : "<<GetName()<<endl;
cout<<"나이 : "<<GetAge()<<endl;
cout<<"전공 : "<<GetMajor()<<endl;
}
};
int main()
{
Student Kim(22,"jslee","computer");
Kim.ShowData();
};
첫번째 예를 보면 전달된 major인자를 빼고는 전부디폴트 매개변수에 의해 초기화가 된것을 볼수가 있는데,이제 우리가 원하는 방식으로 바꿔보자..객체생성시 모두 초기화를 해주자.
그래서 바꾼 코드가 위의 코드이다. 자 어떤가..만족하나? 오..노
age와 name는 상속하고 있긴 하지만 엄연히 다른 클래스의 private멤버이다..
그래서 자기 클래스에서만 접근이 가능하다. 상속하고 있다고 해서 접근 가능한게 아니다.
자.우리는 public로 선언되어있는 그 무언가를 상속하는 클래스에서 조작을 시도할것이다 .
자..Student 클래스의 객체를 생성하면서 인자를 전달해주고있다. 근데 age와 name은 접근을 하지 못해..일단 생성자 호출한담에 뭐?그래 상속되는 클래스로 가야지..상속하고있으니까..가봤더니 생성자가 하나가있다..지금의 Student클래스는 Person의 void 생성자를 호출하고 있으니까 우리가 age,name에 접근을 못한다고....그러니 우린 멤버이니셜라이져 특급
기능을 사용하여..Person생성자로 하여금 Person의 멤버변수 age,name에 접근 할 것이다.
strcpy(major,_major);
}
짜잔..어떤가..Student클래스를 호출하면서 몸체 생성하기전에 Person클래스의 생성자중
인자로 _age,_name을 받을수 있는 생성자를 호출하고있다.자.봤더니 있네?
그 생성자를 호출하고 실행을 했더니.오..Person함수내의 멤버변수에 접근해서 초기화를
해주네 오 ㄳ ..그리고 나서 다시 Student객체생성 마무리 하고..봤더니..
우리가 원하는 데로 초기화가 이루어졌다 ㅋㅋ 이제 정보은닉을 무너트리지 않고 객체생성시 우리가 원하는 데로 초기화를 해줄수 있게 되었습니다 ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ
요거 위에위에 노란 박스 대로 해서 초기화를 하려면 Person클래스의 멤버변수가
public인경우엔 가능하다..근데 그럼 정보은닉이 무너지니까..내가 시킨대로 해라 캬캬
객체 소멸과정의 이해
class AAA{
public:
AAA(){
cout<<"AAA()호출"<<endl;
}
~AAA(){
cout<<"~AAA()호출"<<endl;
}
};
class BBB : public AAA{
public:
BBB(){
cout<<"BBB()호출"<<endl;
}
~BBB(){
cout<<"~BBB()호출"<<endl;
}
};
int main()
{
BBB bbb;
return 0;
}
객체 소멸과정을 보기 위해 우리는 여기서 저기 위의 예제를 볼필요가 있다.
자자 긴장긴장.. 메인함수에서 BBB클래스의 객체 bbb를 생성해 void생성자 호출 ㄱㄱ
생성자 호출할려고가봤더니..어..상속하고있어..그럼 AAA클래스로 ㄱㄱ
void생성자 호출하고 실행해..그담에 다시..BBB생성자 남은 몸체 실행한다.
그담에 bbb객체가 및 BBB클래스가 소멸해야하니까..~BBB()소멸자를 호출하고 없어지겠지. 그럼..상속한 AAA클래스 소멸하려면? 어떻게 하냐?.. 자 상속하고 있는 클래스의 객체는
자신이 상속하고 있는 클래스의 소멸자 까지도 호출한다. 어제는 이해 안가더니 오늘은 이해가네 이말이 ㅋㅋ 결과를 보자.
오~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~케이
4. protected 멤버
간단히 설명하자.
일반적인 관계에서는 private의 성질을 가지고 있지만 상속관계에선 public의 성질을 가진다.
#include <iostream>
class AAA
{
private:
int a;
protected:
int b;
};
class BBB : public AAA{
public:
void SetData(){
a=10; //에러
b=20;
}
};
int main()
{
AAA aaa;
aaa.a=10; //에러
aaa.b=20; //에러
BBB bbb;
bbb.SetData();
return 0;
}
나는 니가 이걸 보고 protected멤버를 이해할수 있으면 소원이 없겠다..자세한설명생략
5. 세가지 형태의 상속
private상속
protected상속
public상속
상속을 하더라도 어떤 상속의 종류이던간에 private멤버는 접근 불가 라는 사실만 명심하자
6. 상속을 하는 이유
이건 따로 공부하자