//: C09:VirtualConstructor.cpp // From Thinking in C++, 2nd Edition // Available at http://www.BruceEckel.com // (c) Bruce Eckel 2000 // Copyright notice in Copyright.txt #include #include #include #include using namespace std; class Shape { Shape* s; // Prevent copy-construction & operator= Shape(Shape&); Shape operator=(Shape&); protected: Shape() { s = 0; }; public: virtual void draw() { s->draw(); } virtual void erase() { s->erase(); } virtual void test() { s->test(); }; virtual ~Shape() { cout << "~Shape\n"; if(s) { cout << "Making virtual call: "; s->erase(); // Virtual call } cout << "delete s: "; delete s; // The polymorphic deletion } class BadShapeCreation : public exception { string reason; public: BadShapeCreation(string type) { reason = "Cannot create type " + type; } const char *what() const { return reason.c_str(); } }; Shape(string type) throw(BadShapeCreation); }; class Circle : public Shape { Circle(Circle&); Circle operator=(Circle&); Circle() {} // Private constructor friend class Shape; public: void draw() { cout << "Circle::draw\n"; } void erase() { cout << "Circle::erase\n"; } void test() { draw(); } ~Circle() { cout << "Circle::~Circle\n"; } }; class Square : public Shape { Square(Square&); Square operator=(Square&); Square() {} friend class Shape; public: void draw() { cout << "Square::draw\n"; } void erase() { cout << "Square::erase\n"; } void test() { draw(); } ~Square() { cout << "Square::~Square\n"; } }; Shape::Shape(string type) throw(Shape::BadShapeCreation) { if(type == "Circle") s = new Circle; else if(type == "Square") s = new Square; else throw BadShapeCreation(type); draw(); // Virtual call in the constructor } char* shlist[] = { "Circle", "Square", "Square", "Circle", "Circle", "Circle", "Square", "" }; int main() { vector shapes; cout << "virtual constructor calls:" << endl; try { for(char** cp = shlist; **cp; cp++) shapes.push_back(new Shape(*cp)); } catch(Shape::BadShapeCreation e) { cout << e.what() << endl; return 1; } for(int i = 0; i < shapes.size(); i++) { shapes[i]->draw(); cout << "test\n"; shapes[i]->test(); cout << "end test\n"; shapes[i]->erase(); } Shape c("Circle"); // Create on the stack cout << "destructor calls:" << endl; for(int j = 0; j < shapes.size(); j++) { delete shapes[j]; cout << "\n------------\n"; } } ///:~