7. 상속(Inheritance)의 이해
출처: 윤성우 열혈강의 C++ 예제코드
7.1. 상속에 들어가기에 앞서
- OOP Handler Class 사용하기
#include <iostream>
#include <cstring>
using namespace std;
class PermanentWorker
{
private:
char name[100];
int salary;
public:
PermanentWorker(char* name, int money)
: salary(money)
{
strcpy(this->name, name);
}
int GetPay() const
{
return salary;
}
void ShowSalaryInfo() const
{
cout<<"name: "<<name<<endl;
cout<<"salary: "<<GetPay()<<endl<<endl;
}
};
class EmployeeHandler
{
private:
PermanentWorker* empList[50];
int empNum;
public:
EmployeeHandler() : empNum(0)
{ }
void AddEmployee(PermanentWorker* emp)
{
empList[empNum++]=emp;
}
void ShowAllSalaryInfo() const
{
for(int i=0; i<empNum; i++)
empList[i]->ShowSalaryInfo();
}
void ShowTotalSalary() const
{
int sum=0;
for(int i=0; i<empNum; i++)
sum+=empList[i]->GetPay();
cout<<"salary sum: "<<sum<<endl;
}
~EmployeeHandler()
{
for(int i=0; i<empNum; i++)
delete empList[i];
}
};
int main(void)
{
// 직원관리를 목적으로 설계된 컨트롤 클래스의 객체생성
EmployeeHandler handler;
// 직원 등록
handler.AddEmployee(new PermanentWorker("KIM", 1000));
handler.AddEmployee(new PermanentWorker("LEE", 1500));
handler.AddEmployee(new PermanentWorker("JUN", 2000));
// 이번 달에 지불해야 할 급여의 정보
handler.ShowAllSalaryInfo();
// 이번 달에 지불해야 할 급여의 총합
handler.ShowTotalSalary();
return 0;
}
7.2. 상속의 문법적인 이해
- 이니셜라이저를 이용한 Base Class 생성자 호출
#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<<"I'm "<<age<<" years old"<<endl;
}
};
class UnivStudent : public Person
{
private:
char major[50]; // 전공과목
public:
UnivStudent(char * myname, int myage, char * mymajor)
: Person(myage, myname)
{
strcpy(major, mymajor);
}
void WhoAreYou() const
{
WhatYourName();
HowOldAreYou();
cout<<"My major is "<<major<<endl<<endl;
}
};
int main(void)
{
UnivStudent ustd1("Lee", 22, "Computer eng.");
ustd1.WhoAreYou();
UnivStudent ustd2("Yoon", 21, "Electronic eng.");
ustd2.WhoAreYou();
return 0;
};
- 유도클래스 객체의 소멸과정
#include <iostream>
using namespace std;
class SoBase
{
private:
int baseNum;
public:
SoBase(int n) : baseNum(n)
{
cout<<"SoBase() : "<<baseNum<<endl;
}
~SoBase()
{
cout<<"~SoBase() : "<<baseNum<<endl;
}
};
class SoDerived : public SoBase
{
private:
int derivNum;
public:
SoDerived(int n) : SoBase(n), derivNum(n)
{
cout<<"SoDerived() : "<<derivNum<<endl;
}
~SoDerived()
{
cout<<"~SoDerived() : "<<derivNum<<endl;
}
};
int main(void)
{
SoDerived drv1(15);
SoDerived drv2(27);
return 0;
};
SoBase() : 15
SoDerived() : 15
SoBase() : 27
SoDerived() : 27
~SoDerived() : 27
~SoBase() : 27
~SoDerived() : 15
~SoBase() : 15
7.3. protected 선언과 세 가지 형태의 상속
- 세 가지 형태의 상속
class Base
{
...
}
class Derived : public Base // private을 제외하고 모두 상속
{
...
}
class Derived : protected Base // protected보다 접근 범위가 넓은 멤버는 protected로 변경하여 상속
{
...
}
class Derived : private Base // 모두 접근이 불가하므로 의미없음
{
...
}
7.4. 상속을 위한 조건
- IS-A 관계의 상속
#include <iostream>
#include <cstring>
using namespace std;
class Computer
{
private:
char owner[50];
public:
Computer(char * name)
{
strcpy(owner, name);
}
void Calculate()
{
cout<<"요청 내용을 계산합니다."<<endl;
}
};
class NotebookComp : public Computer
{
private:
int battary;
public:
NotebookComp(char * name, int initChag)
: Computer(name), battary(initChag)
{ }
void Charging() { battary+=5; }
void UseBattary() { battary-=1; }
void MovingCal()
{
if(GetBattaryInfo()<1)
{
cout<<"충전이 필요합니다."<<endl;
return;
}
cout<<"이동하면서 ";
Calculate();
UseBattary();
}
int GetBattaryInfo() { return battary; }
};
class TabletNotebook : public NotebookComp
{
private:
char regstPenModel[50];
public:
TabletNotebook(char * name, int initChag, char * pen)
: NotebookComp(name, initChag)
{
strcpy(regstPenModel, pen);
}
void Write(char * penInfo)
{
if(GetBattaryInfo()<1)
{
cout<<"충전이 필요합니다."<<endl;
return;
}
if(strcmp(regstPenModel, penInfo)!=0)
{
cout<<"등록된 펜이 아닙니다.";
return;
}
cout<<"필기 내용을 처리합니다."<<endl;
UseBattary();
}
};
int main(void)
{
NotebookComp nc("이수종", 5);
TabletNotebook tn("정수영", 5, "ISE-241-242");
nc.MovingCal();
tn.Write("ISE-241-242");
return 0;
}
- HAS-A 관계의 상속
#include <iostream>
#include <cstring>
using namespace std;
class Gun
{
private:
int bullet; // 장전된 총알의 수
public:
Gun(int bnum) : bullet(bnum)
{ }
void Shut()
{
cout<<"BBANG!"<<endl;
bullet--;
}
};
class Police : public Gun
{
private:
int handcuffs; // 소유한 수갑의 수
public:
Police(int bnum, int bcuff)
: Gun(bnum), handcuffs(bcuff)
{ }
void PutHandcuff()
{
cout<<"SNAP!"<<endl;
handcuffs--;
}
};
int main(void)
{
Police pman(5, 3); // 총알 5, 수갑 3
pman.Shut();
pman.PutHandcuff();
return 0;
}
- HAS-A 상속관계의 다른구현
#include <iostream>
#include <cstring>
using namespace std;
class Gun
{
private:
int bullet; // 장전된 총알의 수
public:
Gun(int bnum) : bullet(bnum)
{ }
void Shut()
{
cout<<"BBANG!"<<endl;
bullet--;
}
};
class Police
{
private:
int handcuffs; // 소유한 수갑의 수
Gun * pistol; // 소유하고 있는 권총
public:
Police(int bnum, int bcuff)
: handcuffs(bcuff)
{
if(bnum>0)
pistol=new Gun(bnum);
else
pistol=NULL;
}
void PutHandcuff()
{
cout<<"SNAP!"<<endl;
handcuffs--;
}
void Shut()
{
if(pistol==NULL)
cout<<"Hut BBANG!"<<endl;
else
pistol->Shut();
}
~Police()
{
if(pistol!=NULL)
delete pistol;
}
};
int main(void)
{
Police pman1(5, 3);
pman1.Shut();
pman1.PutHandcuff();
Police pman2(0, 3); // 권총소유하지 않은 경찰
pman2.Shut();
pman2.PutHandcuff();
return 0;
}