4. 클래스의 완성(윤성우 열혈강의 C++ 예제코드)


출처: 윤성우 열혈강의 C++ 예제코드


4.1. 정보은닉(INFORMATION HIDING)

  • access function을 이용한 private member변수 제어하기
Point.h
#ifndef __POINT_H_
#define __POINT_H_

class Point
{
private:
	int x; 
	int y;    

public:
	bool InitMembers(int xpos, int ypos);
	int GetX() const;
	int GetY() const;
	bool SetX(int xpos);
	bool SetY(int ypos);
};

#endif
Point.cpp
#include <iostream>
#include "Point.h"
using namespace std;

bool Point::InitMembers(int xpos, int ypos)
{
	if(xpos<0 || ypos<0)
	{
		cout<<"벗어난 범위의 값 전달"<<endl;
		return false;
	}
	
	x=xpos;
	y=ypos;
	return true;
}

int Point::GetX() const {return x;}
int Point::GetY() const {return y;}

bool Point::SetX(int xpos)
{
	if(0>xpos || xpos>100)
	{
		cout<<"벗어난 범위의 값 전달"<<endl;
		return false;
	}

	x=xpos;
	return true;
}	
bool Point::SetY(int ypos)
{
	if(0>ypos || ypos>100)
	{
		cout<<"벗어난 범위의 값 전달"<<endl;
		return false;
	}

	y=ypos;
	return true;
}
Rectangle.h
#ifndef __RECTANGLE_H_
#define __RECTANGLE_H_

#include "Point.h"

class Rectangle
{
private:
	Point upLeft;
	Point lowRight;

public:
	bool InitMembers(const Point &ul, const Point &lr);
	void ShowRecInfo() const;
};

#endif
Rectangle.cpp
#include <iostream>
#include "Rectangle.h"
using namespace std;

bool Rectangle::InitMembers(const Point &ul, const Point &lr)
{
	if(ul.GetX()>lr.GetX() || ul.GetY()>lr.GetY())
	{
		cout<<"잘못된 위치정보 전달"<<endl;
		return false;
	}

	upLeft=ul;
	lowRight=lr;
	return true;
}

void Rectangle::ShowRecInfo() const
{
	cout<<"좌 상단: "<<'['<<upLeft.GetX()<<", ";
	cout<<upLeft.GetY()<<']'<<endl;
	cout<<"우 하단: "<<'['<<lowRight.GetX()<<", ";
	cout<<lowRight.GetY()<<']'<<endl<<endl;
}
RectangleFaultFind.cpp
#include<iostream>
#include "Point.h"
#include "Rectangle.h"
using namespace std;

int main(void)
{
	Point pos1;
	if(!pos1.InitMembers(-2, 4))
		cout<<"초기화 실패"<<endl;
	if(!pos1.InitMembers(2, 4))
		cout<<"초기화 실패"<<endl;

	Point pos2;
	if(!pos2.InitMembers(5, 9))
		cout<<"초기화 실패"<<endl;

	Rectangle rec;
	if(rec.InitMembers(pos2, pos1))
		cout<<"직사각형 초기화 실패"<<endl;

	if(rec.InitMembers(pos1, pos2))
		cout<<"직사각형 초기화 실패"<<endl;
	
	rec.ShowRecInfo();
	return 0;
}

4.2. 캡슐화(ENCAPSULATION)


  • 유사패턴의 클래스를 하나의 클래스로 캡슐화 하기
#include <iostream>
using namespace std;

class SinivelCap    // 콧물 처치용 캡슐
{
public: 
	void Take() const {cout<<"콧물이 싹~ 납니다."<<endl;}
};

class SneezeCap    // 재채기 처치용 캡슐
{
public: 
	void Take() const {cout<<"재채기가 멎습니다."<<endl;}
};

class SnuffleCap   // 코막힘 처치용 캡슐
{
public: 
	void Take() const {cout<<"코가 뻥 뚫립니다."<<endl;}
};

class CONTAC600 
{
private:
	SinivelCap sin;
	SneezeCap sne;
	SnuffleCap snu;

public:
	void Take() const
	{
		sin.Take();
		sne.Take();
		snu.Take();
	}
};

class ColdPatient
{
public:
	void TakeCONTAC600(const CONTAC600 &cap) const { cap.Take(); }
};

int main(void)
{
	CONTAC600 cap;
	ColdPatient sufferer;
	sufferer.TakeCONTAC600(cap);
	return 0;
}

4.3. 생성자(CONSTRUCTOR)와 소멸자(DESTRUCTOR)


  • 생성자 오버로딩
#include <iostream>
using namespace std;

class SimpleClass
{
	int num1;
	int num2;

public:
	SimpleClass()
	{
		num1=0;
		num2=0;
	}
	SimpleClass(int n)
	{
		num1=n;
		num2=0;
	}
	SimpleClass(int n1, int n2)
	{
		num1=n1;
		num2=n2;
	}

	/*
	SimpleClass(int n1=0, int n2=0)
	{
		num1=n1;
		num2=n2;
	}
	*/

	void ShowData() const
	{
		cout<<num1<<' '<<num2<<endl;
	}
};

int main(void)
{
	SimpleClass sc1;
	sc1.ShowData();

	SimpleClass sc2(100);
	sc2.ShowData();

	SimpleClass sc3(100, 200);
	sc3.ShowData();
	return 0;
}
  • 멤버 이니셜라이져(Member Initializer)를 이용한 멤버 초기화
Point.h
#ifndef __POINT_H_
#define __POINT_H_

class Point
{
	int x; 
	int y;    
public:
	Point(const int &xpos, const int &ypos);
	int GetX() const;
	int GetY() const;
	bool SetX(int xpos);
	bool SetY(int ypos);
};

#endif
Point.cpp
#include <iostream>
#include "Point.h"
using namespace std;

Point::Point(const int &xpos, const int &ypos)
{
	x=xpos;
	y=ypos;
}

int Point::GetX() const {return x;}
int Point::GetY() const {return y;}

bool Point::SetX(int xpos)
{
	if(0>xpos || xpos>100)
	{
		cout<<"벗어난 범위의 값 전달"<<endl;
		return false;
	}

	x=xpos;
	return true;
}	
bool Point::SetY(int ypos)
{
	if(0>ypos || ypos>100)
	{
		cout<<"벗어난 범위의 값 전달"<<endl;
		return false;
	}

	y=ypos;
	return true;
}
Rectangle.h
#ifndef __RECTANGLE_H_
#define __RECTANGLE_H_

#include "Point.h"

class Rectangle
{
	Point upLeft;
	Point lowRight;

public:
	Rectangle(const int &x1, const int &y1, const int &x2, const int &y2);
	void ShowRecInfo() const;
};

#endif

Rectangle.cpp
#include <iostream>
#include "Rectangle.h"
using namespace std;

Rectangle::Rectangle(const int &x1, const int &y1, const int &x2, const int &y2)
			:upLeft(x1, y1), lowRight(x2, y2)
{
	// empty
}

void Rectangle::ShowRecInfo() const
{
	cout<<"좌 상단: "<<'['<<upLeft.GetX()<<", ";
	cout<<upLeft.GetY()<<']'<<endl;
	cout<<"우 하단: "<<'['<<lowRight.GetX()<<", ";
	cout<<lowRight.GetY()<<']'<<endl<<endl;
}
RectangleConstructor.cpp
#include<iostream>
#include "Point.h"
#include "Rectangle.h"
using namespace std;

int main(void)
{

	Rectangle rec(1, 1, 5, 5);
	rec.ShowRecInfo();
	return 0;
}
  • 멤버 이니셜라이져(Member Initializer)를 이용한 변수 및 상수 초기화
#include <iostream>
using namespace std;

class FruitSeller
{
	const int APPLE_PRICE;
	int numOfApples;
	int myMoney;
public:
	FruitSeller(int price, int num, int money)
		: APPLE_PRICE(price), numOfApples(num), myMoney(money)
	{
	}
	int SaleApples(int money)  
	{
		int num=money/APPLE_PRICE;
		numOfApples-=num;
		myMoney+=money;
		return num;
	}
	void ShowSalesResult() const
	{
		cout<<"남은 사과: "<<numOfApples<<endl;
		cout<<"판매 수익: "<<myMoney<<endl<<endl;
	}
};

class FruitBuyer
{
	int myMoney;
	int numOfApples;
public:
	FruitBuyer(int money)
		: myMoney(money), numOfApples(0)
	{
	}
	void BuyApples(FruitSeller &seller, int money)
	{
		numOfApples+=seller.SaleApples(money);
		myMoney-=money;
	}
	void ShowBuyResult() const
	{
		cout<<"현재 잔액: "<<myMoney<<endl;
		cout<<"사과 개수: "<<numOfApples<<endl<<endl;
	}
};

int main(void)
{
	FruitSeller seller(1000, 20, 0);
	FruitBuyer buyer(5000);
	buyer.BuyApples(seller, 2000);
	
	cout<<"과일 판매자의 현황"<<endl;
	seller.ShowSalesResult();
	cout<<"과일 구매자의 현황"<<endl;
	buyer.ShowBuyResult();
	return 0;
}
  • 소멸자를 이용한 메모리 해제
#include <iostream>
#include <cstring>
using namespace std;

class Person
{
private:
	char * name;
	int age;
public:
	Person(char * myname, int myage)
	{
		int len=strlen(myname)+1;
		name=new char[len];
		strcpy(name, myname);
		age=myage;
	}

	void ShowPersonInfo() const
	{
		cout<<"이름: "<<name<<endl;
		cout<<"나이: "<<age<<endl;
	}
	
	~Person()
	{
		delete []name;
		cout<<"called destructor!"<<endl;
	}
};

int main(void)
{
	Person man1("Lee dong woo", 29);
	Person man2("Jang dong gun", 41);
	man1.ShowPersonInfo();
	man2.ShowPersonInfo();
	return 0;
}

4.4. 클래스와 배열 그리고 THIS 포인터


  • 객체배열 사용하기
#include <iostream>
#include <cstring>
using namespace std;

class Person
{
private:
	char * name;
	int age;
public:
	Person(char * myname, int myage)
	{
		int len=strlen(myname)+1;
		name=new char[len];
		strcpy(name, myname);
		age=myage;
	}
	Person()
	{
		name=NULL;
		age=0;
		cout<<"called Person()"<<endl;
	}
	void SetPersonInfo(char * myname, int myage)
	{
		name=myname;
		age=myage;
	}
	void ShowPersonInfo() const
	{
		cout<<"이름: "<<name<<", ";
		cout<<"나이: "<<age<<endl;
	}	
	~Person()
	{
		delete []name;
		cout<<"called destructor!"<<endl;
	}
};

int main(void)
{
	Person parr[3];

	char namestr[100];
	char * strptr;
	int age;
	int len;

	for(int i=0; i<3; i++)
	{
		cout<<"이름: ";
		cin>>namestr;
		cout<<"나이: ";
		cin>>age;

		len=strlen(namestr)+1;
		strptr=new char[len];
		strcpy(strptr, namestr);
		parr[i].SetPersonInfo(strptr, age);	
	}

	parr[0].ShowPersonInfo();
	parr[1].ShowPersonInfo();
	parr[2].ShowPersonInfo();
	return 0;
}
  • 포인터배열 사용하기
#include <iostream>
#include <cstring>
using namespace std;

class Person
{
private:
	char * name;
	int age;
public:
	Person(char * myname, int myage)
	{
		int len=strlen(myname)+1;
		name=new char[len];
		strcpy(name, myname);
		age=myage;
	}
	Person()
	{
		name=NULL;
		age=0;
		cout<<"called Person()"<<endl;
	}
	void SetPersonInfo(char * myname, int myage)
	{
		name=myname;
		age=myage;
	}
	void ShowPersonInfo() const
	{
		cout<<"이름: "<<name<<", ";
		cout<<"나이: "<<age<<endl;
	}	
	~Person()
	{
		delete []name;
		cout<<"called destructor!"<<endl;
	}
};

int main(void)
{
	Person * parr[3];

	char namestr[100];
	char * strptr;
	int age;
	int len;

	for(int i=0; i<3; i++)
	{
		cout<<"이름: ";
		cin>>namestr;
		cout<<"나이: ";
		cin>>age;

		parr[i]=new Person(namestr, age);
	}

	parr[0]->ShowPersonInfo();
	parr[1]->ShowPersonInfo();
	parr[2]->ShowPersonInfo();

	delete parr[0];
	delete parr[1];
	delete parr[2];
	return 0;
}
  • this 포인터 사용하기
#include <iostream>
#include <cstring>
using namespace std;

class SoSimple
{
	int num;
public:
	SoSimple(int n) : num(n)
	{
		cout<<"num="<<num<<", ";
		cout<<"address="<<this<<endl;
	}

	void ShowSimpleData()
	{
		cout<<num<<endl;
	}

	SoSimple * GetThisPointer()
	{
		return this;
	}
};

int main(void)
{
	SoSimple sim1(100);
	SoSimple * ptr1=sim1.GetThisPointer();
	cout<<ptr1<<", ";
	ptr1->ShowSimpleData();

	SoSimple sim2(200);
	SoSimple * ptr2=sim2.GetThisPointer();
	cout<<ptr2<<", ";
	ptr2->ShowSimpleData();
	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