📄 pizza1.cpp
字号:
// Get needed include files
#define INITGUID
#include "Pizza1.h"
#include "Utility.h"
// Support dynamic creation
IMPLEMENT_DYNCREATE(ComPizzaOrderTaker, CCmdTarget)
// Support a class factory
// {47DD0D53-641F-11d0-8C23-00400539F36B}
IMPLEMENT_OLECREATE(ComPizzaOrderTaker, "PizzaOrderTaker1",
0x47DD0D53, 0x641F, 0x11d0, 0x8C, 0x23, 0x0, 0x40, 0x5, 0x39, 0xF3, 0x6B);
// Map the various interfaces onto the nested interface classes
BEGIN_INTERFACE_MAP(ComPizzaOrderTaker, CCmdTarget)
INTERFACE_PART(ComPizzaOrderTaker, IID_IPizzaOrderTaker, CInnerPizza)
END_INTERFACE_MAP()
// List of base pizza prices
ULONG g_aulPizzaPrices[] =
{
395, // Individual
595, // Small
795 // Large
};
// List of base topping prices
ULONG g_aulToppingPrices[] =
{
50, // Individual
100, // Small
150 // Large
};
// List of topping modifiers (topping prices are influenced by the size of
// the pizza, but some toppings -- like artichokes YECH! -- are twice as
// expensive)
ULONG g_aulToppingMods[] =
{
0, // Not a topping (here to catch errors)
1, // Pepperoni
1, // Sausage
1, // GroundBeef
1, // GreenOlives
1, // ProsciuttiniHam
1, // Pastrami
1, // GreenPeppers
1, // Mushrooms
1, // Onions
1, // Tomatoes
1, // Pesto
1, // JalapenoPeppers
1, // CheddarCheese
1, // FontinaCheese
1, // RicottaCheese
1, // FetaCheese
1, // Pineapple
1, // ExtraCheese
1, // Bacon
1, // Broccoli
1, // GenoaSalami
1, // Zucchini
1, // BlackOlives
1, // Anchovies
2, // ChickenBreast
2, // Shrimp
2 // ArtichokeHearts
};
//
// Constructor and destructor
//
ComPizzaOrderTaker::ComPizzaOrderTaker()
: m_eSize(Individual)
{
VerboseMsg("In PizzaOrderTaker constructor.\n");
// Allow other components to aggregate us if they need to
EnableAggregation();
AfxOleLockApp();
}
ComPizzaOrderTaker::~ComPizzaOrderTaker()
{
VerboseMsg("In PizzaOrderTaker destructor.\n");
// Call reset to free up memory in the topping list
m_xCInnerPizza.ResetPizza();
AfxOleUnlockApp();
}
//
// Nested PizzaOrderTaker IUnknown members
//
STDMETHODIMP_(ULONG)
ComPizzaOrderTaker::XCInnerPizza::AddRef()
{
METHOD_PROLOGUE(ComPizzaOrderTaker, CInnerPizza)
return pThis->ExternalAddRef();
}
STDMETHODIMP_(ULONG)
ComPizzaOrderTaker::XCInnerPizza::Release()
{
METHOD_PROLOGUE(ComPizzaOrderTaker, CInnerPizza)
return pThis->ExternalRelease();
}
STDMETHODIMP
ComPizzaOrderTaker::XCInnerPizza::QueryInterface(REFIID riid, PPVOID ppv)
{
METHOD_PROLOGUE(ComPizzaOrderTaker, CInnerPizza)
return pThis->ExternalQueryInterface(&riid, ppv);
}
//
// IPizzaOrderTaker interface members for nested PizzaOrderTaker class
//
STDMETHODIMP
ComPizzaOrderTaker::XCInnerPizza::ResetPizza()
{
METHOD_PROLOGUE(ComPizzaOrderTaker, CInnerPizza)
VerboseMsg("In ResetPizza.\n");
// Clean out the topping list
POSITION posCurrent = pThis->m_ToppingList.GetHeadPosition();
while (posCurrent) {
delete pThis->m_ToppingList.GetNext(posCurrent);
}
pThis->m_ToppingList.RemoveAll();
// Reset the size to Individual
pThis->m_eSize = Individual;
return NOERROR;
}
STDMETHODIMP
ComPizzaOrderTaker::XCInnerPizza::SetPizzaSize(PizzaSize eNewSize)
{
METHOD_PROLOGUE(ComPizzaOrderTaker, CInnerPizza)
VerboseMsg("In SetPizzaSize.\n");
// Set the new size
pThis->m_eSize = eNewSize;
return NOERROR;
}
STDMETHODIMP
ComPizzaOrderTaker::XCInnerPizza::GetPizzaSize(PizzaSize* peCurrSize)
{
METHOD_PROLOGUE(ComPizzaOrderTaker, CInnerPizza)
VerboseMsg("In GetPizzaSize.\n");
// Get the current size
if (peCurrSize)
*peCurrSize = pThis->m_eSize;
return NOERROR;
}
STDMETHODIMP
ComPizzaOrderTaker::XCInnerPizza::AddTopping(Topping eNewTopping,
ToppingSize eNewToppingSize)
{
METHOD_PROLOGUE(ComPizzaOrderTaker, CInnerPizza)
VerboseMsg("In AddTopping.\n");
// Is this topping already in the list?
if (pThis->FindTopping(eNewTopping))
return E_FAIL;
// Create a new Topping tuple
CToppingTuple* pTuple = new CToppingTuple;
pTuple->eTopping = eNewTopping;
pTuple->eToppingSize = eNewToppingSize;
// Add the topping to the list
pThis->m_ToppingList.AddTail(pTuple);
return NOERROR;
}
STDMETHODIMP
ComPizzaOrderTaker::XCInnerPizza::RemoveTopping(Topping eRemTopping)
{
METHOD_PROLOGUE(ComPizzaOrderTaker, CInnerPizza)
VerboseMsg("In RemoveTopping.\n");
// Find the topping tuple
POSITION posTopping = pThis->FindTopping(eRemTopping);
if (!posTopping)
return NOERROR;
// We need to free the memory for the tuple
delete pThis->m_ToppingList.GetAt(posTopping);
// And now remove the list element
pThis->m_ToppingList.RemoveAt(posTopping);
return NOERROR;
}
STDMETHODIMP
ComPizzaOrderTaker::XCInnerPizza::GetNumToppings(ULONG* pulNumToppings)
{
METHOD_PROLOGUE(ComPizzaOrderTaker, CInnerPizza)
VerboseMsg("In GetNumToppings.\n");
// Get the current number of toppings
if (pulNumToppings)
*pulNumToppings = pThis->m_ToppingList.GetCount();
return NOERROR;
}
STDMETHODIMP
ComPizzaOrderTaker::XCInnerPizza::GetTopping(ULONG ulListPos,
Topping* peTopping,
ToppingSize* peToppingSize)
{
METHOD_PROLOGUE(ComPizzaOrderTaker, CInnerPizza)
VerboseMsg("In GetTopping.\n");
//
// Retrieve the position's tuple
//
// GetTopping() provides position-oriented retrieval because it's easy
// to manipulate and understand. However, since the toppings are actually
// stored in a list, positioned access is slow. Definitely room for
// improvement here.
//
// Validate the list position
if (ulListPos >= pThis->m_ToppingList.GetCount())
return E_FAIL;
// Go to the head of the list
POSITION posCurrent = pThis->m_ToppingList.GetHeadPosition();
if (!posCurrent)
return E_FAIL;
// Iterate through the list, counting
ULONG ulCurrentElem = 0UL;
CToppingTuple* pTuple = NULL;
while (posCurrent) {
// Is this a match?
CToppingTuple* pTuple = pThis->m_ToppingList.GetNext(posCurrent);
if (ulCurrentElem == ulListPos) {
*peTopping = pTuple->eTopping;
*peToppingSize = pTuple->eToppingSize;
return NOERROR;
}
ulCurrentElem++;
}
return E_FAIL;
}
STDMETHODIMP
ComPizzaOrderTaker::XCInnerPizza::GetPizzaPrice(ULONG* pulPrice)
{
METHOD_PROLOGUE(ComPizzaOrderTaker, CInnerPizza)
VerboseMsg("In GetPizzaPrice.\n");
// Start by setting the base price.
ULONG ulPizzaPrice = g_aulPizzaPrices[pThis->m_eSize];
// Now walk through the topping list, adding to the current price
POSITION posCurrent = pThis->m_ToppingList.GetHeadPosition();
CToppingTuple* pTuple = NULL;
while (posCurrent) {
// Get the current topping
pTuple = pThis->m_ToppingList.GetNext(posCurrent);
// Calculate the topping price
ULONG ulToppingPrice = g_aulToppingPrices[pThis->m_eSize] *
g_aulToppingMods[pTuple->eTopping];
// Based on how much of the pizza is covered with this topping, the
// topping price needs to be scaled
switch (pTuple->eToppingSize)
{
case FullPizza: break; // Do nothing
case HalfPizza: ulToppingPrice /= 2; break;
case QuarterPizza: ulToppingPrice /= 4; break;
}
// Add the topping priuce to the total
ulPizzaPrice += ulToppingPrice;
}
// And now return the result
*pulPrice = ulPizzaPrice;
return NOERROR;
}
STDMETHODIMP
ComPizzaOrderTaker::XCInnerPizza::OrderPizza(DeliveryInfo* , // pDeliveryInfo,
CreditCard , // eCreditCardType,
BSTR , // bstrCreditCardNum,
ULONG* pulPrice)
{
METHOD_PROLOGUE(ComPizzaOrderTaker, CInnerPizza)
VerboseMsg("In OrderPizza.\n");
// Set the price
GetPizzaPrice(pulPrice);
// Do whatever needs to be done to send the order out
// (We'll do some things here in Part II of the book)
return NOERROR;
}
POSITION ComPizzaOrderTaker::FindTopping(Topping eSearchTopping)
{
// This is about as slow and inefficient a design as you could imagine
// I use a linear search here simple to keep the code simple
// Go to the head of the list
POSITION posCurrent = m_ToppingList.GetHeadPosition();
if (!posCurrent)
return NULL;
// Iterate through the list, looking for the requested topping
POSITION posPrev;
CToppingTuple* pTuple = NULL;
while (posCurrent) {
// Is this a match?
posPrev = posCurrent;
pTuple = m_ToppingList.GetNext(posCurrent);
if (pTuple->eTopping == eSearchTopping)
return posPrev;
}
return NULL;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -