B
babaco
Hi,
I've come upon a situation where I don't understand what's happening.
Basically, I'm implementing a kind of 'chain of responsibility' using
some covariant types:
#include <iostream>
#include <string>
#include <vector>
using namespace std;
class Shape {
public:
int sides;
};
class Square : public Shape {
public:
int sides;
Square() : sides(4) {};
};
class Triangle : public Shape {
public:
int sides;
Triangle() : sides(3) {};
};
class ShapeMaker {
public:
virtual Shape* CreateObject(void) const = 0;
};
class SquareMaker : public ShapeMaker {
public:
Square* CreateObject(void) const {
cout << "CreateObject: for SQUARE" << endl;
return (new Square);
}
};
class TriangleMaker : public ShapeMaker {
public:
Triangle* CreateObject(void) const {
cout << "CreateObject: for TRIANGLE" << endl;
return (new Triangle);
}
};
class ShapeContainer {
private:
vector<Square*> squares;
vector<Triangle*> triangles;
vector<Shape*> shapes;
public:
void enter(Square* s) { squares.push_back(s); }
void enter(Triangle* t) { triangles.push_back(t); }
void enter(Shape* s) { shapes.push_back(s); }
friend ostream& operator<<(ostream& os, ShapeContainer &c) {
return os << "Container has \t" << c.squares.size() << " squares
\n"
<< " \t" << c.triangles.size() << "
triangles\n"
<< " \t" << c.shapes.size() << " generic shapes
\n";
}
};
int main ()
{
SquareMaker* sfactory = new SquareMaker;
TriangleMaker* tfactory = new TriangleMaker;
cout << "\nFirst Set of Tests:" << endl;
ShapeContainer container1;
container1.enter(sfactory->CreateObject());
container1.enter(tfactory->CreateObject());
cout << container1;
cout << "\n\nSecond Set of Tests:" << endl;
vector<ShapeMaker*> master_factory;
master_factory.push_back(sfactory);
master_factory.push_back(tfactory);
ShapeContainer container2;
vector<ShapeMaker*>::iterator it = master_factory.begin();
while(it != master_factory.end()) {
// this calls the correct derived type function
// but returns an object of the base class. huh?
container2.enter( (*it)->CreateObject() );
++it;
}
cout << container2;
}
This compiles under gcc 4.0.1 (apple, x86). When I run it I get this:
First Set of Tests:
CreateObject: for SQUARE
CreateObject: for TRIANGLE
Container has 1 squares
1 triangles
0 generic shapes
Second Set of Tests:
CreateObject: for SQUARE
CreateObject: for TRIANGLE
Container has 0 squares
0 triangles
2 generic shapes
My question is why does (*it)->CreateObject() call the correct derived
class type, but result in a base class return type? Please be gentle;
I've been writing Perl code for years now and I'm lazy and used to
dynamic bindings.
TIA
I've come upon a situation where I don't understand what's happening.
Basically, I'm implementing a kind of 'chain of responsibility' using
some covariant types:
#include <iostream>
#include <string>
#include <vector>
using namespace std;
class Shape {
public:
int sides;
};
class Square : public Shape {
public:
int sides;
Square() : sides(4) {};
};
class Triangle : public Shape {
public:
int sides;
Triangle() : sides(3) {};
};
class ShapeMaker {
public:
virtual Shape* CreateObject(void) const = 0;
};
class SquareMaker : public ShapeMaker {
public:
Square* CreateObject(void) const {
cout << "CreateObject: for SQUARE" << endl;
return (new Square);
}
};
class TriangleMaker : public ShapeMaker {
public:
Triangle* CreateObject(void) const {
cout << "CreateObject: for TRIANGLE" << endl;
return (new Triangle);
}
};
class ShapeContainer {
private:
vector<Square*> squares;
vector<Triangle*> triangles;
vector<Shape*> shapes;
public:
void enter(Square* s) { squares.push_back(s); }
void enter(Triangle* t) { triangles.push_back(t); }
void enter(Shape* s) { shapes.push_back(s); }
friend ostream& operator<<(ostream& os, ShapeContainer &c) {
return os << "Container has \t" << c.squares.size() << " squares
\n"
<< " \t" << c.triangles.size() << "
triangles\n"
<< " \t" << c.shapes.size() << " generic shapes
\n";
}
};
int main ()
{
SquareMaker* sfactory = new SquareMaker;
TriangleMaker* tfactory = new TriangleMaker;
cout << "\nFirst Set of Tests:" << endl;
ShapeContainer container1;
container1.enter(sfactory->CreateObject());
container1.enter(tfactory->CreateObject());
cout << container1;
cout << "\n\nSecond Set of Tests:" << endl;
vector<ShapeMaker*> master_factory;
master_factory.push_back(sfactory);
master_factory.push_back(tfactory);
ShapeContainer container2;
vector<ShapeMaker*>::iterator it = master_factory.begin();
while(it != master_factory.end()) {
// this calls the correct derived type function
// but returns an object of the base class. huh?
container2.enter( (*it)->CreateObject() );
++it;
}
cout << container2;
}
This compiles under gcc 4.0.1 (apple, x86). When I run it I get this:
First Set of Tests:
CreateObject: for SQUARE
CreateObject: for TRIANGLE
Container has 1 squares
1 triangles
0 generic shapes
Second Set of Tests:
CreateObject: for SQUARE
CreateObject: for TRIANGLE
Container has 0 squares
0 triangles
2 generic shapes
My question is why does (*it)->CreateObject() call the correct derived
class type, but result in a base class return type? Please be gentle;
I've been writing Perl code for years now and I'm lazy and used to
dynamic bindings.
TIA