I have a simple Shape
factory example where I can create Circle
s or Square
s.
I have added an extra "contents
" attribute to the Circle
class that is not part of the Square
derived class or the Shape
base class.
The problem is, when I create an instance of the Circle
class using my factory, I am unable to modify the contents
of the created object.
#include <iostream>
using namespace std;
// Shape base clas
class Shape {
public:
// Shape constructor;
Shape() {
id_ = total_++;
}
// Virtual draw method
virtual void draw() = 0;
protected:
int id_;
static int total_;
};
int Shape::total_ = 0;
// Circle derived class
class Circle : public Shape {
public:
void draw() {
contents = 0;
cout << "circle " << id_ << ": draw, contents: " << contents << endl;
}
// Attribute to attempt to access
int contents;
};
// Square derived class
class Square : public Shape {
public:
void draw() {
cout << "square " << id_ << ": draw" << endl;
}
};
// Factory class
class Factory {
public:
Shape* createCurvedInstance() {
return new Circle;
}
Shape* createStraightInstance() {
return new Square;
}
};
// Main
int main()
{
Factory* factory = new Factory;
Shape* thing = factory->createCurvedInstance();
// Draw method works fine (as it should)
thing->draw();
// Fails: "expression must have class type"
thing.contents = 4;
system("pause");
return 0;
}
How can I access attributes of the derived class when I create an instance of it using a factory?
It turns out I didn't want a factory at all!
What I really wanted was some sort of container class to hold different types of shapes. Neither shape is derived from the ShapeContainer
class but both shapes can be accessed through it.
#include <iostream>
using namespace std;
// Circle class
class Circle {
public:
Circle() {
contents = 2;
}
void draw() {
cout << "circle " << contents << endl;
}
int contents;
};
// Square class
class Square {
public:
void draw() {
cout << "square" << endl;
}
};
// Shape containter class
class ShapeContainer {
public:
Circle* getCircle() {
return new Circle;
}
Square* getSquare() {
return new Square;
};
};
// Main
int main()
{
ShapeContainer* container = new ShapeContainer;
Circle* circle = container->getCircle();
circle->draw();
circle->contents = 42;
circle->draw();
system("pause");
return 0;
}
This allows me to make both Circle
s and Square
s while still being able to access the contents of the Circle
object!
Sometimes you need to look at things from a whole new perspective to get the functionality you really want...