C++ クラスを作ってみる 構築編

http://www.idea-tech.net/index.htm

こちらを参考にしました。


問題は、

八百屋さん計算システムを以下の仕様とガイドラインにしたがって
コマンドライン・アプリケーションとして設計してください。

仕様:

りんご、バナナ、トマト(野菜)、にんじんが商品である。
りんごの仕入れ値は300円、定価は400円。
バナナの仕入れ値は200円、定価は300円。
トマトの仕入れ値は30円、定価は50円。
にんじんの仕入れ値は50円、定価は70円。
それぞれ仕入れ数を入力すると、総仕入額が表示
売り上げがある度にお客様一人のお買い上げ金額と総売り上げ、各品物の残数を表示。
いつも全ての品物が5%引きである。
火曜日は全ての果物は値引き額から更に10%引きである。
りんごは5個パックで買うと 値引き額からさらに5%引きである。
バナナは3房パックで買うと、値引き額からさらに3%引きである。
木曜日全ての野菜は4個買うともう1個おまけで付いてくる。
ガイドライン:

各品物はクラスとして設計してください。
事前に必要なクラスを列挙してみる。
継承図を使って継承関係がないか、検討してみる。
入力数値の範囲チェックは行わなくて良い。
仕入れ数入力と販売時の入力は別の状態として設計する。
品物の種類が増えることはないことを前提にして良い。

赤い文字のところからまずは地道にやっていく。
全体図を作ってみる。

商品:仕入れ値、定価、値率、残数
    果物:
        リンゴ
        バナナ
    野菜
        トマト
        ニンジン

だいたい概要はこんな感じ。初めてなので、商品クラスから地道に作っていく。
Product.h

#ifndef PRODUCT_H_
#define PRODUCT_H_

class Product {
public:
	Product(const int nCostPrice, const int nListPrice, int nRestCount);
	virtual ~Product();
private:
	const int m_nCostPrice; //仕入れ値
	const int m_nListPrice;  //定価
        //privateには、virtualを宣言することができない。
	int m_nSellPrice(); //1っ個当たりの売値
	double m_nRate; //1-値引き率
	int m_nRestCount; //仕入れた数
	bool Confirm(int cnt); //売る数が残数を上回っていないか確認
	int m_nWholeCost; //累計仕入れ値総額
	int m_nWholeSales; //累計売上総額
public:
	void GetStockNumber(int cnt); //仕入れ数を入力すると、総仕入れ額が表示される。
        //商品ごとにもれなくもう一個サービスやるので、オーバーライドすると思って
        //virtualを手前に置く。
	virtual void SellProduct(int cnt); //売る
	virtual void Disp(); //状態を表示
	void DispProfit(); //利益を表示
};

#endif


Product.cpp

#include "Product.h"
#include 
using namespace std;

//コンストラクタ
//[仕入れ値、定価、仕入れた数]を引数にとる
Product::Product(const int nCostPrice, const int nListPrice, int nRestCount)
:m_nCostPrice(nCostPrice), m_nListPrice(nListPrice)
{
	m_nRestCount = nRestCount;
	m_nRate = 0.9;
	m_nWholeCost = nRestCount * nCostPrice;
	m_nWholeSales = 0;
}
//デストラクタ
Product::~Product()
{
}
//売値
int Product::m_nSellPrice() {
	return int(m_nListPrice * m_nRate);
}
//仕入れ数を入力すると、総仕入れ額が表示される。
void Product::GetStockNumber(int cnt) {
	m_nRestCount += cnt;
	cout << "今回の総仕入れ額:" << cnt * m_nCostPrice << "円" <//累計総仕入れ額が加算される。
	m_nWholeCost += cnt * m_nCostPrice;
	cout << "累計総仕入れ額:" << m_nWholeCost << "円" << endl;
}

//売る数が残数を上回っていないか確認
bool Product::Confirm(int cnt) {
	if(cnt > m_nRestCount) {
		return false;
	} else {
		;
	}
	return true;
}

//全体表示
void Product::Disp() {
	cout << "仕入れ値:" << m_nCostPrice << endl;
	cout << "定価:" << m_nListPrice << endl;
	cout << "売値:" << m_nSellPrice() << endl;
	cout << "1-値引き率:" << m_nRate << endl;
	cout << "仕入れた数:" << m_nRestCount << endl;
	cout << "前回からの総仕入れ額:" << m_nWholeCost << endl;
	cout << "累計売上額:" << m_nWholeSales << endl;
}
//利益を表示
void Product::DispProfit() {
	cout << "利益:" << m_nWholeSales - m_nWholeCost << endl;
}

//売る
void Product::SellProduct(int cnt) {
	//売る量が残数を上回っていないか確認
	if(Confirm(cnt)) {
		m_nRestCount = m_nRestCount-cnt;
	}
	//呼びかけ
	cout << cnt * m_nSellPrice() << "になります。"<< endl;
	//売上金を加算
	m_nWholeSales += cnt * m_nSellPrice();
}


main.cpp

#include "Product.h"
//#include "Fruit.h"
//#include "Vegetable.h"
#include 
using namespace std;

int main() {
	Product* apple = new Product(300, 400, 30);
	cout << "----apple->Disp();--------" << endl;
	apple->Disp();
	cout << "----apple->DispProfit();---------" << endl;
	apple->DispProfit();
	cout << "----SellProduct(14);-----------" << endl;
	apple->SellProduct(14);
	cout << "-----------------------------------" << endl;
	apple->DispProfit();
	cout << "-----------------------------------" << endl;
	apple->Disp();
	cout << "----GetStockNumber(10);---------" << endl;
	apple->GetStockNumber(10);
	cout << "-----------------------------------" << endl;
	apple->DispProfit();
	cout << "-----------------------------------" << endl;
	apple->Disp();
	cout << "------------------------------------" << endl;
	delete apple;
}

後で付け加えたところはもじを小さくしてみた。ちゃんとうまくできてる。
コメントつけるまでもないね。

----apple->Disp();--------
仕入れ値:300
定価:400
売値:360
1-値引き率:0.9
仕入れた数:30
前回からの総仕入れ額:9000
累計売上額:0
----apple->DispProfit();---------
利益:-9000
----SellProduct(14);-----------
5040になります。
-----------------------------------
利益:-3960
-----------------------------------
仕入れ値:300
定価:400
売値:360
1-値引き率:0.9
仕入れた数:16
前回からの総仕入れ額:9000
累計売上額:5040
----GetStockNumber(10);---------
今回の総仕入れ額:3000円
累計総仕入れ額:12000円
-----------------------------------
利益:-6960
-----------------------------------
仕入れ値:300
定価:400
売値:360
1-値引き率:0.9
仕入れた数:26
前回からの総仕入れ額:12000
累計売上額:5040
------------------------------------
続行するには何かキーを押してください . . .


外に出ているProductクラスの仕様は次の通り。

Productクラス

class product
{
public:
/コンストラクタ
//[仕入れ値、定価、仕入れた数]を引数にとる
//仕入れ額を計算して、累計のほうに代入。
//値率を初期化しておく。
//総売り上げはもちろん0なので、初期化しておく。
Product::Product(const int nCostPrice, const int nListPrice, int nRestCount)
:m_nCostPrice(nCostPrice), m_nListPrice(nListPrice);

//仕入れ数を入力すると、今回の仕入れ額累計総仕入れ額が表示される。
//もちろん、仕入れ数も加算された状態になる。
	void GetStockNumber(int cnt);

//売る行為を関数化したもの。在庫が足りなかったら販売中止。それ以外は
//順当に売って、売上金を加算する。
	virtual void SellProduct(int cnt);

//protectedは外からは見えないので、Disp()関数を通して変数の値が見れるようにする。
	void Disp(); //状態を表示
	void DispProfit(); //利益を表示
};