I think my problem is that C++ cannot work with class instances without initializing them in a more explicit way than I am doing, but I'm not sure how to go about doing that.... maybe there's an easy solution but it isn't obvious to me. does someone see another approach to this? or a way to make this forward declaration work?

two main errors I'm getting are:
1) forward declaration of struct 'Topping' (after the first line - class Topping;)
2) invalid use of undefined type struct 'Topping' (class Sausage : public Topping)

#include <string>
#include <list>
#include <iostream>
using namespace std;

class Topping;
class Sausage : public Topping
	{
	public:
		string name() {return "Sausage";}
		int cost(){return 200;}
		char c(){return 'S';}
	};
class ExtraCheese : public Topping
	{
	public:
		string name() {return "Extra Cheese";}
		int cost(){return 185;}
		char c(){return 'E';}
	};
class Hamburger : public Topping
	{
	public:
		string name() {return "Hamburger";}
		int cost(){return 200;}
		char c(){return 'H';}
	};
class Pepperoni : public Topping
	{
	public:
		string name() {return "Pepperoni";}
		int cost(){return 200;}
		char c(){return 'P';}
	};
class CanadianBacon : public Topping
	{
	public:
		string name() {return "Canadian Bacon";}
		int cost(){return 275;}
		char c(){return 'C';}
	};
class Onions : public Topping
	{
	public:
		string name() {return "Onions";}
		int cost(){return 150;}
		char c(){return 'O';}
	};
class Beer : public Topping
	{
	public:
		string name() {return "Beer";}
		int cost(){return 325;}
		char c(){return 'B';}
	};
class Small : public Topping
	{
	public:
		string name() {return "Small";}
		int cost(){return 800;}
		char c(){return 's';}
	};
class Medium : public Topping
	{
	public:
		string name() {return "Medium";}
		int cost(){return 1000;}
		char c(){return 'm';}
	};
class Large : public Topping
	{
	public:
		string name() {return "Large";}
		int cost(){return 1200;}
		char c(){return 'l';}
	};
class Family : public Topping
	{
	public:
		string name() {return "Family";}
		int cost(){return 1600;}
		char c(){return 'f';}
	};

class Topping
	{
	public:
		static Topping * new_topping(char c)
		{
			switch(c)
			{
				case 'S':
					return new Sausage;
				case 'E':
					return new ExtraCheese;
				case 'P':
					return new Pepperoni;
				case 'H':
					return new Hamburger;
				case 'C':
					return new CanadianBacon;
				case 'O':
					return new Onions;
				case 'B':
					return new Beer;
				case 's':
					return new Small;
				case 'm':
					return new Medium;
				case 'l':
					return new Large;
				case 'f':
					return new Family;
					
			}
		}
		
		virtual string name();
		virtual int cost();
		virtual char c();
	};

class Pizza				// singleton pattern (manages THE pizza)
	{
	public:
		static void createPizza();
		static void printReceipt();
		static void createPizza(char size, string toppings);
		static void addToppings(string toppings);
		static void removeToppings(string toppings);
		static void changeSize(char size);

		static list<Topping*> pizza;
	};

list<Topping*> Pizza::pizza = list<Topping*>(); // initializes to an empty list

int main(){
	
	std::cout << "Making empty pizza...\n";
	Pizza::createPizza();
	Pizza::printReceipt();			// includes printing the cost
	
	std::cout << "Making large, spc pizza\n";
	Pizza::createPizza('L', "spc");
	Pizza::printReceipt();			// includes printing the cost
	
	Pizza::addToppings("of");
	Pizza::printReceipt();			// includes printing the cost
	
	Pizza::removeToppings("");			
	Pizza::printReceipt();			// includes printing the cost
	
	Pizza::changeSize('L');
	Pizza::printReceipt();			// includes printing the cost
	
	Pizza::createPizza();
	Pizza::printReceipt();			// test to make sure this pizza prints empty
	
	
    cout << "Hello" << endl;
	return 0;
}

void Pizza::createPizza()
{
	for(list<Topping*>::iterator i = Pizza::pizza.being(); i != Pizza::pizza.end(); i++)
	{
		delete(i);
	}
	Pizza::pizza.clear;
	
}

void Pizza::createPizza(char size, string toppings)
{
	for (list<Topping*>::iterator i = Pizza::pizza.begin(); i!= Pizza::pizza.end(); i++)
	{ delete(i); }
	Pizza::pizza.clear();	// resets the pizza everytime createPizza is called
	
	Pizza::pizza.push(Topping::new_topping(size));
	
	Pizza::addToppings(toppings);
}
void Pizza::addToppings(string toppings)
{
	for(string::iterator t = toppings.begin(); t != toppings.end(); t++)
	{
		Pizza::pizza.push(Topping::new_topping(*t);
	}       
}
						 
void Pizza::changeSize(char size)
{
list<Topping*>::iterator i;
i = Pizza::pizza.begin();
delete(i);
Pizza::pizza.replace(i, Topping::new_topping(size));
}
void Pizza::removeToppings(string toppings)
{
	//  validate input
	for (string::iterator r = toppings.begin(); r!= toppings.end(); r++) 
	{
		for (list<Topping*>::iterator i = Pizza::pizza.begin(); i!= Pizza::pizza.end(); i++)
		{
				if ( i->c(); == *r)
				{
					i=Pizza::pizza.erase(i);  // increments iterator
					i--;   //  decerement interator to counteract incrementation 
				}
		}
	}
} // removeToppings(..)
				
void Pizza::printReceipt()
{
	int total = 0;
	for (list<Topping*>::iterator i = Pizza::pizza.begin(); i!= Pizza::pizza.end(); i++)
	{
		cout << i->name();
		total += i->cost();
	}
}

A quick solution to what you want is to just move your topping selector to the Pizza class since you pretty much have a circular reference with your derived class sitting inside of your base class.

I threw together a simplified version of what I think you are trying to accomplish.

#include <iostream>
#include <list>
#include <string>
using namespace std;

class Topping
{
	public:
	Topping(){};

	virtual void print() = 0;
};

class Cheese: public Topping
{
	public:
	Cheese(){};

	void print()
	{
		cout << "Cheese!" << endl;
	}
};

class Pepperoni: public Topping
{
	public:
	Pepperoni(){};

	void print()
	{
		cout << "Pepperoni!" << endl;
	}
};

class Pizza
{
	list<Topping*> toppings;
	public:
	Pizza(){};

	void AddToppings(string ts)
	{
		for( string::iterator t = ts.begin(); t != ts.end(); t++ )
			switch(*t)
			{
				case 'c':
					toppings.push_back(new Cheese);
					break;

				case 'p':
					toppings.push_back(new Pepperoni);
					break;

				default:
					break;
			}
	}

	void PrintToppings()
	{
		for( list<Topping*>::iterator t = toppings.begin(); t != toppings.end(); t++ )
			(*t)->print();
	}
};

int main()
{
	Pizza *p = new Pizza();
	p->AddToppings("cp");
	p->PrintToppings();
	return 0;
}

I haven't played around with special class patterns but I'm pretty sure that "Pizza" is not a singleton class. In fact what you have is the same as wrapping a few functions and variables in a namespace (since you are not making use of private/protected from the class).

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.