본문 바로가기

Programming/C++ 2

[C++] 10장-2. 추상화와 클래스

반응형

클래스와 클래스 메서드 정의

//stock00.h
//version 00

#ifndef STOCCK00_H_ //전처리 지시자 #define에 정의되어 있지 않은 경우에만,
#define STOCK00_H_ // #ifndef와 #endif 사이에 있는 구문을 처리

#include<string>

class Stock
{
private:
	std::string company;
	long shares;
	double share_val;
	double total_val;
	void set_tot() { total_val = shares * share_val; }
public:
	void acquire(const std::string& co, long n, double pr);
	void buy(long num, double price);
	void sell(long num, double price);
	void update(double price);
	void show();
}; //class 끝에 ;

#endif
//stock00.cpp
//version 00
#include <iostream>
#include "stock00.h"

void Stock::acquire(const std::string& co, long n, double pr) //해당 회사 주식 첫 취득
// 멤버함수를 정의할 때, 그 멤버 함수가 어느 클래스에 속하는지 나타내는 사용 범위 결정 연산자
{
	company = co;
	if (n < 0)
	{
		std::cout << "주식 수는 음수가 될 수 없으므로,"
			<< company << " shares를 0으로 설정합니다. \n";
		shares = 0;
	}
	else
		shares = n;
	share_val = pr;
	set_tot();
}
void Stock::buy(long num, double price) //기존 보유 주식의 증가와 감소 관리
{
	if (num < 0)
	{
		std::cout << "매입 주식 수는 음수가 될 수 없으므로, "
			<< "거래가 취소되었습니다.\n";
	}
	else
	{
		shares += num;
		share_val = price;
		set_tot();
	}
}
void Stock::sell(long num, double price) //기존 보유 주식의 감소 관리
{
	using std::cout;
	if (num < 0)
	{
		cout << "모두 주식 수는 음수가 될 수 없으므로, "
			<< "거래가 취소되었습니다. \n";
	}
	else if (num >shares)
	{
		cout << "보유 주식보다 많은 주식을 매도할 수 없으므로, "
			<< "거래가 취소되었습니다. \n";
	}
	else
	{
		shares -= num;
		share_val = price;
		set_tot();
	}
}
void Stock::update(double price)
{
	share_val = price;
	set_tot();
}

void Stock::show()
{
	std::cout << "회사명: " << company
		<< " 주식 수: " << shares << '\n'
		<< " 주가: $" << share_val
		<< " 주식 총 가치: $" << total_val << '\n';
}

 

acquire() : 해당 회사 주식의 첫 취득을 관리

buy(), sell() : 기존 보유 주식의 증가와 감소 관리

매입 주식 수 또는 매도 주식 수가 음수가 될 수 없게 관리

보유하고 있는 주식보다 많은 주식을 매도하려고 시도하는 경우 sell()함수에서 거래 취소

 

total_val 멤버의 값 : 네 개의 멤버 함수가 설정 / 재설정

 

-> 각 함수로 하여금 set_tot() 함수 호출로 멤버의 값을 설정하는 계산을 각각 작성을 방지

-> set_tot()는 private 멤버함수 [클래스 자체를 작성한 사람이 사용하는 멤버함수]

-> 계산을 수정할 경우에 set_tot() 함수만 수정 가능

 


클래스 객체 생성하고 사용하는 프로그램 작성

 

//usestock0.cpp -- 고객 프로그램
//stock00.cpp와 컴파일
#include <iostream>
#include "stock00.h"
int main()
{
	Stock fluffy_the_cat;
	fluffy_the_cat.acquire("NanoSmart", 20, 12.50);
	fluffy_the_cat.show();
	fluffy_the_cat.buy(15, 18.125);
	fluffy_the_cat.show();
	fluffy_the_cat.sell(400, 20.00);
	fluffy_the_cat.show();
	fluffy_the_cat.buy(300000, 40.125);
	fluffy_the_cat.show();
	fluffy_the_cat.sell(300000, 0.125);
	fluffy_the_cat.show();
	return 0;
}

-> 일관적이지 않은 숫자 양식

 

 

setf()를 사용해 표기상의 문제를 피한다

 

std::cout.setf(std::ios_base::fixed, std::ios_base::floatfiled);

-> 플래그를 고정 소수점 표기를 사용하기 위해 cout 개체 안에 플래그를 세팅

 

std::cout.precision(3);

-> cout로 고점 소수점 표기를 사용할 때, 소수점 이하 세 자리까지 보여주도록 세팅

-> 17장. 입력 출력 파일

 

메서드에 대한 변경 상항을 구현할 때는 클라이언트 프로그램의 다른 부분에 영향을 미치지 않도록

show()가 호출되기 이전의 상태로 정보를 리셋

 

std::streamsize prec=
std:: cout.precision(3); //정확성을 위해서 이전 값을 저장

...
std::cout.precision(prec); //과거 값으로 리턴

//원본 플래그를 저장
std::ios_base::fmtflags orig=std::cout.setf(std::ios_base::fixed);
...

//저장된 값을 리셋
std::cout.setf(orig, std::ios_base::floatfield);

-> fmtflags : ios_base클래스에 정의된 데이터형

-> orig : 모든 플래그를 보유하고 리셋 구문은 그 정보를 사용해 고정 소수점 표기와 플래그를 포함하고 있는floatfioeld에 있는 정보를 리셋

-> 변화된 내용들이 해당 파일에 한정되고 다른 부분에 영향을 미치지 않는다.

 

//version 00
#include <iostream>
#include "stock00.h"

void Stock::acquire(const std::string& co, long n, double pr) //해당 회사 주식 첫 취득
// 멤버함수를 정의할 때, 그 멤버 함수가 어느 클래스에 속하는지 나타내는 사용 범위 결정 연산자
{
	company = co;
	if (n < 0)
	{
		std::cout << "주식 수는 음수가 될 수 없으므로,"
			<< company << " shares를 0으로 설정합니다. \n";
		shares = 0;
	}
	else
		shares = n;
	share_val = pr;
	set_tot();
}
void Stock::buy(long num, double price) //기존 보유 주식의 증가와 감소 관리
{
	if (num < 0)
	{
		std::cout << "매입 주식 수는 음수가 될 수 없으므로, "
			<< "거래가 취소되었습니다.\n";
	}
	else
	{
		shares += num;
		share_val = price;
		set_tot();
	}
}
void Stock::sell(long num, double price) //기존 보유 주식의 감소 관리
{
	using std::cout;
	if (num < 0)
	{
		cout << "모두 주식 수는 음수가 될 수 없으므로, "
			<< "거래가 취소되었습니다. \n";
	}
	else if (num >shares)
	{
		cout << "보유 주식보다 많은 주식을 매도할 수 없으므로, "
			<< "거래가 취소되었습니다. \n";
	}
	else
	{
		shares -= num;
		share_val = price;
		set_tot();
	}
}
void Stock::update(double price)
{
	share_val = price;
	set_tot();
}


void Stock::show()
{
	using std::cout;
	using std::ios_base;//fmtflags가 ios_base 클래스, std 이름공간에서 정의
	//set format #.###
	ios_base::fmtflags orig = //orig가 긴 타입 이름이 된다.
		cout.setf(ios_base::fixed, ios_base::floatfield);
	std::streamsize prec = cout.precision(3);

	cout << "회사명: " << company
		<< " 주식 수: " << shares << '\n';
	cout << " 주가: $" << share_val;
	//set format to #.##
	cout.precision(2);
	cout << " 주식 총 가치: $" << total_val << '\n';

	//restore original format
	cout.setf(orig, ios_base::floatfield);
	cout.precision(prec);
}


클래스 설계

1. 클래스 선언을 제공

class className
{
private:
	data member declarations
public:
	member function prototype
};

-> private 부분의 멤버는 멤버 함수를 통해서만 접근

-> public 부분에 선언된 멤버들은 클래스 객체를 사용해 직접 접근 [추상화 부분인 public 인터페이스]

 

2. 클래스 멤버 함수를 구현

멤버함수가 어느 클래스에 속하는지 나타내기 위해 사용 범위 결정 연산자 '::' 를 사용 

char* Bozo::Retort()

 

클래스의 객체를 생성

Bozo bozetta;

 

클래스 객체를 사용함으로써 클래스 멤버함수를 호출

cout<<bozetta.Retort();

 

반응형