// File "ListTest.cc". C++ translation of ListTest.java, by KWR, Assgt. 1. // Few comments in this file, so you can compare syntax with the C++ version. // Study Guide: understand or ask about every "///" comment, and then delete // them so that the code doesn't keep looking so cluttered. // Commented-out lines show some optional alternatives. For features such as // const and ":" constructor-initializer syntax and "virtual", you get credit // if you used them *somewhere*, while "explicit" was not on grading scheme. // Delete all //commented-out lines to see a minimal perfect answer. #include #include #include #include ///needed for "dynamic_cast" translating Java "instanceof" using namespace std; ///needed for Sun CC but not g++ with default settings //------------------------------------------------------------------------- #include // for sprintf (KLUDGE) string itoa(long int x) { //Converts [long, short] int to an ANSI string. char b[100]; sprintf(b, "%d", x); string s = b; return s; } //------------------------------------------------------------------------- class Foo{ string fooVal; public: Foo() : fooVal("Empty") { } explicit Foo(string str) : fooVal(str) { } ///disables Foo x = "hello"; Foo(int x) : fooVal(itoa(x)) { } ///no "explicit" enables Foo x = 5; virtual string getFooVal() const { return fooVal; } virtual void setFooVal(string newFooVal) { fooVal = newFooVal; } virtual string toString() const { return "My fooVal is " + fooVal; } //virtual operator const char* () { return fooVal.c_str(); } }; ///^^^try commenting this in and doing cout << *q->get() << endl below; class FooList { public: class Cell { ///nested Cell class---syntax is same way as in Java. public: Foo* info; ///you would need a ~Cell() destructor to delete this field Cell* next; explicit Cell(Foo* info) : info(info), next(this) { } ///Cell(Foo* inf) : info(inf), next(this) { } ///also OK. Cell(Foo* info, Cell* n) : info(info), next(n) { } // virtual ~Cell() { delete(info); } ///we will do "real" data-structure }; ///destructors later, using high-level code to empty them, then cleanup. ///To Study: "delete(rear);" causes infinite-loop in circle-linked list. private: Cell* rear; ///Note: Java "default" access must == "public" in C++, or use "friend". ///(friend will be taught later) public: FooList() : rear(new Cell(new Foo(0))) { } //virtual ~FooList() { delete(rear); } virtual bool empty() const { return rear == rear->next; } virtual void add(Foo* i) { rear->info = i; rear = rear->next = new Cell(new Foo(0), rear->next); } virtual void push(Foo* i) { rear->next = new Cell(i, rear->next); } virtual Foo* get() const { ///To Study: this satisfies the compiler def^n ///of "const" but not the meaningful def^n. if( empty() ) return new Foo(); Cell* front = rear->next; rear->next = front->next; ///unlinks node //Foo* temp = new Foo(front->info); //delete(front); ///really deletes node //return temp; return front->info; } }; class Queue: public FooList { public: Queue() : FooList() { } ///see note in "Stack" //virtual ~Queue() { } ///ditto virtual Foo* get() const { return FooList::get(); } virtual void put(Foo* x) { add(x); } ///"FooList::add" AOK but not needed. }; class Stack: public FooList { public: ///OK to omit call to base-class zero-parameter (aka. "default") Stack() { } ///constructor since it is called automatically before the { }, //virtual ~Stack() { } ///while base-class destructor is called after { }. virtual Foo* pop() { return get(); } virtual void push(Foo* x) { FooList::push(x); } //See IMPT NOTE below. }; int main() { Stack* s = new Stack(); Queue* q = new Queue(); int n = 9; for(int i = 1; i <= n; i++) { s->push(new Foo(i)); q->put(new Foo(i)); } cout << "Stack\t\tQueue\n"; for(int i = 1; i <= n; i++) { cout << s->pop()->toString() << "\t"; cout << q->get()->toString() << endl; //cout << *(q->get()) << endl; ///only if you enable "operator char*()" } //delete(s); delete(q); ///good but not required since program is exiting }