Treat vector of SubClass as vector of SuperClass

E

Ed

Let's say I to classes, SuperClass and SubClass (the latter a sub class of the former). I have a vector of SubClasses, but I want to pass them to an API method somewhere that requires a vector of SuperClasses. What is the easiest way for me to go about passing the vector<SubClass> I have on hand to the API method which requires a vector<SuperClass>?

The code I'm working on is a little to convoluted right now to past in, so I came up with what I believe to be an equivalent example in a much more simplified problem domain. In the example, I have a Greeter class that knows how to greet someone. There are specialized version of this class that knowhow to greet males and females (MaleGreeter and FemaleGreeter respectively). My question is, how do I achieve what I am trying to achieve in the commented out line (it won't compile with this line uncommented):
greetAll(maleGreeters);

Please forgive me for compiling my code against Boost in this example. I don't have a C++ 11 compliant compiler yet. I believe the classes I'm using from boost are included in the new C++ 11 standard (I recognize that this list is for standard C++ questions only).

Anyway, here's the code (followed by a short explanation of the real problem I'm trying to solve):

#include <iostream>
#include <string>
#include <vector>
#include <boost/shared_ptr.hpp>
#include <boost/make_shared.hpp>

using std::cout; using std::endl;
using std::string; using std::vector;
using boost::shared_ptr; using boost::make_shared;

/*
* Greeter
*/
class Greeter{
public:
Greeter(string ln);
string greet();
virtual string getFormalAddress(string lastName) = 0;
protected:
string lastName;
};

Greeter::Greeter(string ln){
lastName = ln;
}

string Greeter::greet(){
return "Hello " + getFormalAddress(lastName);
}

/*
* MaleGreeter
*/
class MaleGreeter : public Greeter{
public:
MaleGreeter(string ln);
string getFormalAddress(string lastName);
};

MaleGreeter::MaleGreeter(string ln) : Greeter(ln) {}

string MaleGreeter::getFormalAddress(string lastName){
return "Mr. " + lastName;
}

/*
* FemaleGreeter
*/
class FemaleGreeter : public Greeter{
public:
FemaleGreeter(string ln);
string getFormalAddress(string lastName);
};

FemaleGreeter::FemaleGreeter(string ln) : Greeter(ln) {}

string FemaleGreeter::getFormalAddress(string lastName){
return "Ms. " + lastName;
}

/*
* greetAll()
*/
void greetAll(vector<shared_ptr<Greeter> > greeters);

void greetAll(vector<shared_ptr<Greeter> > greeters){
for( vector<shared_ptr<Greeter> >::iterator i = greeters.begin();
i != greeters.end(); i++){
cout << (*i)->greet() << endl;
}
}

/*
* main()
*/
int main(int argc, char** argv){
//Example 1
shared_ptr<Greeter> g = make_shared<MaleGreeter>(string("MacDonald"));
cout << g->greet() << endl << endl;

//Example 2
vector<shared_ptr<Greeter> > greeters;
greeters.push_back(make_shared<MaleGreeter>("Jones"));
greeters.push_back(make_shared<FemaleGreeter>("Doe"));
greeters.push_back(make_shared<MaleGreeter>("Smith"));
greeters.push_back(make_shared<FemaleGreeter>("Johnson"));
greetAll(greeters);
cout << endl;

//Example 3
vector<shared_ptr<MaleGreeter> > maleGreeters;
greeters.push_back(make_shared<MaleGreeter>("Jones"));
greeters.push_back(make_shared<MaleGreeter>("Smith"));
//How do I make this line work?
//greetAll(maleGreeters);
}
// End of code

So, the real problem I'm trying to solve is that I'm trying to write a chess rules engine. In my code, I have a representation of a chess board in a Board class of my own making. The representation in the Board class of the actual board is a member variable of this type:
vector<vector<shared_ptr<Square> > >
where Square is another class of my making. Square extends a virtual class,AsciiRenderable. AsciiRenderables are passed to an AsciiRendering framework which I intend to have print the representation of the board out on the terminal.

In other words, I wish the framework to operate on things with this signature:
vector<vector<shared_ptr<AsciiRenderable> > >

and Ideally, I would like to have it believe that
vector<vector<shared_ptr<Square> > > ISA vector<vector<shared_ptr<AsciiRenderable> > >

As I write this, I do realize that the ISA relationship there cannot be true because you can add elements to the latter that cannot be elements of theformer (anything that is AsciiRenderable yet not a Square). But is there asimple way to achieve what I seek?

Thanks,
Ed
 
I

Ian Collins

On 03/ 5/12 09:27 AM, Ed wrote:

[please try and wrap lines!]

So, the real problem I'm trying to solve is that I'm trying to write a chess rules engine. In my code, I have a representation of a chess board in a Board class of my own making. The representation in the Board class of the actual board is a member variable of this type:
vector<vector<shared_ptr<Square> > >
where Square is another class of my making. Square extends a virtual class, AsciiRenderable. AsciiRenderables are passed to an AsciiRendering framework which I intend to have print the representation of the board out on the terminal.

In other words, I wish the framework to operate on things with this signature:
vector<vector<shared_ptr<AsciiRenderable> > >

and Ideally, I would like to have it believe that
vector<vector<shared_ptr<Square> > > ISA vector<vector<shared_ptr<AsciiRenderable> > >

As I write this, I do realize that the ISA relationship there cannot be true because you can add elements to the latter that cannot be elements of the former (anything that is AsciiRenderable yet not a Square). But is there a simple way to achieve what I seek?

One solution would be to derive your vector classes privately form
std::vector:

#include <vector>
#include <tr1/memory>

struct AsciiRenderable {};
struct Square : AsciiRenderable {};

typedef std::tr1::shared_ptr<AsciiRenderable> Ptr;
typedef std::tr1::shared_ptr<Square> SquarePtr;

struct Vector : private std::vector<Ptr>
{
using std::vector<Ptr>::push_back;
};

struct SquareVector : Vector {};

void f( Vector& );

int main() {
SquareVector v;

v.push_back(SquarePtr(new Square));

f(v);
}
 
J

Jorgen Grahn

Let's say I to classes, SuperClass and SubClass (the latter a sub
class of the former). I have a vector of SubClasses, but I want to
pass them to an API method somewhere that requires a vector of
SuperClasses. What is the easiest way for me to go about passing the
vector<SubClass> I have on hand to the API method which requires a
vector<SuperClass>?

(Please don't use overlong lines! I reformatted the above manually.)

....
void greetAll(vector<shared_ptr<Greeter> > greeters){
for( vector<shared_ptr<Greeter> >::iterator i = greeters.begin();
i != greeters.end(); i++){
cout << (*i)->greet() << endl;
}
}
....

I don't know if you've considered it or if it's reasonable in your
real-world code, but how about using template functions?

greetAll() could be templatized on an iterator type and take a (begin,
end) range. Or it could be templatized on a container type and take a
const container& parameter.

/Jorgen
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,482
Members
44,901
Latest member
Noble71S45

Latest Threads

Top