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