
객체지향 프로그래밍의 이해
C++에서 말하는 객체(Object)의 의미는 이것이다.
"사물, 또는 대상"
즉, Object는 우리 주변에 존재하는 물건(연필, 지갑 등)이나 대상(철수, 친구, 선생님 등) 전부를 의미한다. 그렇다면 객체지향 프로그래밍으 무엇인가? 예를 들어서 다음 상황을 시뮬레이션 하는 프로그램을 구현한다고 가정해보자.

객체지향 프로그래밍에서는 나, 과일장수, 사과 라는 객체를 등장시켜 두 개의 사과 구매라는 행위를 실체화한다.
즉, 객체지향 프로그래밍은 현실에 존재하는 사물과 대상, 그리고 그에 따른 행동을 있는 그대로 실체화 시키는 형태의 프로그래밍이다.
객체를 이루는 것은 데이터와 기능입니다.
프로그램상에 과일장수 객체가 존재한다고 가정해보자. 프로그램상에서 바라보는 과일장수의 관점은 '과일의 판매'에 있다. 따라서 프로그램상에서 바라보는 과일장수는 다음과 같은 형태이다.

이처럼 객체는 하나 이상의 상태 정보(데이터)와 하나 이상의 행동(기능)으로 구성이 되며, 상태 정보는 변수를 통해 표현이 되고(변수에 상태 정보를 저장할 수 있으므로), 행동은 함수를 통해 표현된다.
그럼 과일장수의 상태 정보를 변수로 표현해보자.
(사과만 판매한다고 가정)

다음에는 과일장수의 행위인 과일의 판매를 함수로 표현해보자.

자 이제 이들을 묶어 객체로 실체화하기만 하면 된다.
'과일장수'의 정의와 멤버변수의 상수화에 대한 논의
객체 생성에 앞서 객체 생성을 위한 틀을 먼저 만들어야 한다. '나' 또는 '과일장수' 객체를 생성하기 위해 이 둘을 위한 틀을 위에서 표현해놓은 함수와 변수를 이용해 만들면 다음과 같다.

위 사진에서 보면 사과의 가격을 의미하는 멤버변수 APPLE_PRICE는 값이 변하지 않는다. 사과 가격이 팔 때마다 변동이 되진 않을거니깐 말이다. 근데 변하지 않으면 변수가 아니라 상수가 아닌가?
하지만 여기서 const로 초기화를 하면 안된다. 이는 불가능하다. 클래스의 멤버변수 선언문에서 초기화까지 하는 것을 허용하지 않기 때문이다.
그러면 const로 선언만 하면 안될까? 이 역시 불가능하다. 상수는 선언과 동시에 초기화되어야 하기 때문이다. 즉, APPLE_PRICE를 상수로 선언할 방법이 없다.
'나(me)'를 표현하는 클래스 정의
'나(me)'를 표현하기 위한 클래스를 정의해보자. 여기서 '나(me)'는 과일 구매자를 뜻하는 것이니 클래스의 이름을 FruitBuyer라 하자.
구매자에 있어서는 상품을 구매할 때 '돈'이 필요할 것이고, 구매를 했다면 해당 '물품'을 소유하게 될 것이다. 따라서 다음의 두 변수를 FruitBuyer 클래스의 멤버변수로 생각할 수 있다.
자 이제 기능적 측면을 생각해보자. 과일 구매자는 '과일의 구매'라는 기능을 지닐 것이다. 따라서 이 기능을 담당할 함수를 클래스에 추가해야 한다. 이 함수의 이름을 BuyApple이라 해보자.

클래스 기반의 두 가지 객체생성 방법
앞에서 FruitSeller 클래스, FruitBuyer 클래스를 정의했다. 클래스를 실체화하기 위해서는 '객체화'를 시켜야한다. C++에서 정의하고 있는 객체 생성 방법으로는 아래의 두 가지 방법이 있다.
ClassName objName;
//일반적인 변수의 선언방식
ClassName *ptrObj = new ClassName;
//동적 할당방식(힙 할당방식)
즉, 우리가 정의한 FruitSeller 클래스와 FruitBuyer을 위와 같이 생성하면!

사과장수 시뮬레이션 완료!
예제를 완성해보자!
FruitSaleSlim1.cpp
#include <iostream>
using namespace std;
class FruitSeller
{
private:
int APPLE_PRICE; //사과 가격
int numOfApples; //남은 사과의 갯수
int myMoney; //판매자가 번 돈
public:
void InitMembers(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; // 인자로 받은 money를 판매자가 번돈에 더함
return num; //판매한 과일의 수를 반환
}
void ShowSalesResult()
{
cout<<"남은 사과 : "<<numOfApples<<endl;
cout<<"판매 수익 : "<<myMoney<<endl<<endl;
}
};
class FruitBuyer
{
int myMoney; // private: //구매자가 가지고 있는 돈
int numOfApples; // private: //구매자가 사간 사과의 갯수
public:
void InitMembers(int money)
{
myMoney=money;
numOfApples=0; //처음엔 사과를 사간게 없으니 당연히 0으로 초기화
}
void BuyApples(FruitSeller &seller, int money)
{
numOfApples+=seller.SaleApples(money);
//FruitSeller에 있는 SaleApples함수에서는 판매한 사과의 수를 반환하므로
// 판매자가 판매한 사과의 갯수 == 구매자가 사간 사과의 갯수
myMoney-=money; //사과 값만큼 가지고 있는 돈에서 뺌
}
void ShowBuyResult()
{
cout<<"현재 잔액: "<<myMoney<<endl;
cout<<"사과 개수: "<<numOfApples<<endl<<endl;
}
};
int main(void)
{
FruitSeller seller; //객체 생성
seller.InitMembers(1000, 20, 0);
//판매자가 사과를 1000원에 팔고, 총 20개를 가지고 있음, 판매자가 번 돈은 0원
FruitBuyer buyer; //객체 생성
buyer.InitMembers(5000); // 구매자는 5000원을 가지고 있음
buyer.BuyApples(seller, 2000); //과일의 구매! 2000원어치 구매
cout<<"과일 판매자의 현황"<<endl;
seller.ShowSalesResult();
cout<<"과일 구매자의 현황"<<endl;
buyer.ShowBuyResult();
return 0;
}
과일 판매자의 현황
남은 사과 : 18
판매 수익 : 2000
과일 구매자의 현황
현재 잔액: 3000
사과 개수: 2
이 예제에서 유심히 봐야할 부분이 있는데, 두 객체가 서로 대화를 하는 모습이다.
buyer.BuyApples(seller, 2000);
이 행에서 FruitBuyer의 객체인 buyer의 함수 BuyApples를 호출하고 있다. 그리고 BuyApples함수 안에서는 FruitSeller의 객체인 seller의 함수 SaleApples를 호출한다.
이처럼 하나의 객체가 다른 하나의 객체에게 메시지를 전달하는 방법은(어떠한 행위의 요구를 위한 메시지 전달) 함수호출을 기반으로 한다.
그래서 객체지향에서는 이러한 형태의 함수호출을 가리켜 '메세지 전달(Message Passing)'이라 한다.