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;
}

Table of contents


Open source project on GitHub


Jupyter/IPython Notebook


Open API


NoSQL


Jekyll


Gradle


Kotlin


C++

  • C++ keywords
  • 윤성우 열혈강의 C++ 프로그래밍 예제코드 [펼치기]
    1. C언어 기반의 C++ 1
      • printf와 scanf를 대신하는 입출력 방식
      • 함수 오버로딩(Function Overloading)
      • 매개변수의 디폴트 값(Default Value)
      • 인라인 함수(Inline)함수
      • 이름공간(namespace)에 대한 소개
    2. C언어 기반의 C++ 2
      • 새로운 자료형 bool
      • 참조자(Reference)의 이해
      • 참조자(Reference)와 함수
      • maloc & free를 대신하는 new & delete
      • C++에서 C언어의 표준함수 호출하기
    3. 클래스의 기본
      • C++에서의 구조체
      • 클래스(Class)와 객체(Object)
      • 객체지향 프로그래밍의 이해
    4. 클래스의 완성
      • 정보은닉(Information Hiding)
      • 캡슐화(Encapsulation)
      • 생성자(Constructor)와 소멸자(Destructor)
      • 클래스와 배열 그리고 this 포인터
    5. 복사 생성자
      • ‘복사 생성자’ 와의 첫 만남
      • ‘깊은 복사’와 ‘얕은 복사’
      • 복사 생성자의 호출시점
    6. friend와 static 그리고 const
      • const와 관련해서 아직 못다한 이야기
      • 클래스와 함수에 대한 friend 선언
      • C++에서의 static
    7. 상속(Inheritance)의 이해
      • 상속에 들어가기에 앞서
      • 상속의 문법적인 이해
      • protected 선언과 세 가지 형태의 상속
      • 상속을 위한 조건
    8. 상속과 다형성
      • 객체 포인터의 참조관계
      • 가상함수(Vitual Function)
      • 가상 소멸자와 참조자의 참조 가능성
    9. 가상(Virtual)의 원리와 다중상속
      • 멤버함수와 가상함수의 동작원리
      • 다중상속(Multiple Inheritance)에 대한 이해
    10. 연산자 오버로딩 1
      • 연산자 오버로딩의 이해와 유형
      • 단항 연산자의 오버로딩의
      • 교환법칙 문제의 해결
      • cout, cin 그리고 endl의 정체
    11. 연산자 오버로딩 2
      • 반드시 해야 하는 대입 연산자의 오버로딩
      • 배열의 인덱스 연산자 오버로딩
      • 그 이외의 연산자 오버로딩
    12. String 클래스의 디자인
      • C++ 표준과 표즌 string 클래스
      • 문자열 처리 클래스의 정의
    13. 템플릿(Template) 1
      • 템플릿(Template)에 대한 이해와 함수 템플릿
      • 클래스 템플릿(Class Temlpate)
    14. 템플릿(Template) 2
      • Chapter 13에서 공부한 내용의 확장
      • 클래스 템플릿의 특수화(Class Temlpate Specialization)
      • 템플릿의 인자
      • 템플릿과 static
    15. 예외처리(Exception Handling)
      • 예외상황과 예외처리의 이해
      • C++의 예외처리 메커니즘
      • Stack Unwinding(스택 풀기)
      • 예외상황을 표현하는 예외 클래스의 설계
      • 예외처리와 관련된 또 다른 특성들
    16. C++의 형 변환 연산자
      • C++에서의 형 변환 연산

ETC