Polymorphism, iterators and ABCs?

  • Thread starter Steven T. Hatton
  • Start date
S

Steven T. Hatton

I've run into a situation where the conventional thinking doesn't seem
satisfactory. I have a table of data where each row maps into a struct. I
want to put these into a vector. My overall design uses interfaces for
everything accessed from outside of the namespace. I also have a class
that acts as a wrapper for the structs. For example:

struct Row { long _col0; long _col1; };

class TableRow_IF {
public:
virtual long getCol0() const = 0;
virtual long getCol1() const = 0;
virtual ~TableRow_IF(){}
};

using std::istream;

class TableRow: public TableRow_IF {
bool _foreignEndian;
Row _row;

public:

TableRow(istream& in, istream::pos_type pos, bool foreignEndian_){
/*read the row data*/
}

virtual long getCol0() const {
return _foreignEndian? reendian(_row._col0): _row._col0;
}

virtual long getCol1() const {
return _foreignEndian? reendian(_row._col1): _row._col1;
}

virtual ~TableRow_IF(){}
};


That works. All the user needs to know about is TableRow_IF. But now I
want a collection of rows. I can't make a std::vector<TableRow_IF> because
that would require the instantiation of an abstract class. I can make a
std::vector<TableRow_IF*>, but that is less safe. Even if I use a smart
pointer, I might still inadvertently attempt to dereference a null pointer.
I can create a std::vector<TableRow>, but then I no longer have
polymorphism when I access the elements.

What I want is this:

class Table_IF {
// acts like a std::vector<TableRow_IF>, except it copmiles.
virtual TableInfo() const = 0;// information about the table

};

class Table: public Table_IF {
// derive from std::vector<TableRow> ??????
virtual TableInfo() const { return _info; }
//...
};

Is there a standard C++ pattern for addressing this kind of situation?

This may prove to be the best approach for the entire project:
http://www.research.att.com/~bs/matrix.c

I believe it's what I will try now for the situation described above.
 
C

Chris Theis

Steven T. Hatton said:
I've run into a situation where the conventional thinking doesn't seem
satisfactory. I have a table of data where each row maps into a struct. I
want to put these into a vector. My overall design uses interfaces for
everything accessed from outside of the namespace. I also have a class
that acts as a wrapper for the structs. For example:
[SNIP]

What use do you have for a vector of the interface implementations? The only
thing that comes off the top of my head would be that you would probably
want to switch between the implementations and in this case I'd recommend
that you go for a PIMPL idiom. Probably you could elaborate on what you want
to achieve.

Cheers
Chris
 
B

benben

Steven T. Hatton said:
I've run into a situation where the conventional thinking doesn't seem
satisfactory. I have a table of data where each row maps into a struct. I
want to put these into a vector. My overall design uses interfaces for
everything accessed from outside of the namespace. I also have a class
that acts as a wrapper for the structs. For example:

struct Row { long _col0; long _col1; };

class TableRow_IF {
public:
virtual long getCol0() const = 0;
virtual long getCol1() const = 0;
virtual ~TableRow_IF(){}
};

using std::istream;

class TableRow: public TableRow_IF {
bool _foreignEndian;
Row _row;

public:

TableRow(istream& in, istream::pos_type pos, bool foreignEndian_){
/*read the row data*/
}

virtual long getCol0() const {
return _foreignEndian? reendian(_row._col0): _row._col0;
}

virtual long getCol1() const {
return _foreignEndian? reendian(_row._col1): _row._col1;
}

virtual ~TableRow_IF(){}
};


That works. All the user needs to know about is TableRow_IF. But now I
want a collection of rows. I can't make a std::vector<TableRow_IF> because
that would require the instantiation of an abstract class. I can make a
std::vector<TableRow_IF*>, but that is less safe. Even if I use a smart
pointer, I might still inadvertently attempt to dereference a null pointer.
I can create a std::vector<TableRow>, but then I no longer have
polymorphism when I access the elements.

What I want is this:

class Table_IF {
// acts like a std::vector<TableRow_IF>, except it copmiles.
virtual TableInfo() const = 0;// information about the table

};

class Table: public Table_IF {
// derive from std::vector<TableRow> ??????
virtual TableInfo() const { return _info; }
//...
};

Is there a standard C++ pattern for addressing this kind of situation?

This may prove to be the best approach for the entire project:
http://www.research.att.com/~bs/matrix.c

I believe it's what I will try now for the situation described above.

--
If our hypothesis is about anything and not about some one or more
particular things, then our deductions constitute mathematics. Thus
mathematics may be defined as the subject in which we never know what we
are talking about, nor whether what we are saying is true.-Bertrand
Russell

If your vector is homogeneous (all elements are of the same type), then just
use that type:

vector<TableRow> table(100);

If your vector is heterogeneous, then vector<Table_IF*> isn't too bad an
idea.

Ben

I don't know if there is a standard practice.
 
R

Roland Pibinger

I've run into a situation where the conventional thinking doesn't seem
satisfactory.

.... you mean conventional STL-thinking :)
I have a table of data where each row maps into a struct. I
want to put these into a vector. My overall design uses interfaces for
everything accessed from outside of the namespace. I also have a class
that acts as a wrapper for the structs. For example:

struct Row { long _col0; long _col1; };

class TableRow_IF {
public:
virtual long getCol0() const = 0;
virtual long getCol1() const = 0;
virtual ~TableRow_IF(){}
};

using std::istream;

class TableRow: public TableRow_IF {
bool _foreignEndian;
Row _row; [...]
};


That works. All the user needs to know about is TableRow_IF. But now I
want a collection of rows. I can't make a std::vector<TableRow_IF> because
that would require the instantiation of an abstract class.

.... and would slice your derived objects.
I can make a
std::vector<TableRow_IF*>, but that is less safe. Even if I use a smart
pointer, I might still inadvertently attempt to dereference a null pointer.
I can create a std::vector<TableRow>, but then I no longer have
polymorphism when I access the elements.

STL is deliberately designed for values only (a.k.a. 'value
semantics'). It doesn't support OO-programming (polymorphism).
What I want is this:

class Table_IF {
// acts like a std::vector<TableRow_IF>, except it copmiles.
virtual TableInfo() const = 0;// information about the table

};

class Table: public Table_IF {
// derive from std::vector<TableRow> ??????
virtual TableInfo() const { return _info; }
//...
};
Is there a standard C++ pattern for addressing this kind of situation?

What you probably want is a container with 'reference semantics'.
There is no standard STL pattern for that. Many other libraries
provide special containers for pointers. One way is to write your own
STL-compliant container for pointers (to non-copyable entity objects)
with reference semantics. See e.g.

http://www.codeproject.com/vcpp/stl/ptr_vecto.asp

It doesn't completely fulfill all your requirements (e.g. insert of a
NULL is only assert-ed). But, IMO, it's the best STL-compliant
solution you can get WRT reference semantics (but, of course, I'm a
little biased).

Best wishes,
Roland Pibinger
 
K

Kai-Uwe Bux

Steven T. Hatton wrote:

[snip]
That works. All the user needs to know about is TableRow_IF. But now I
want a collection of rows. I can't make a std::vector<TableRow_IF>
because
that would require the instantiation of an abstract class. I can make a
std::vector<TableRow_IF*>, but that is less safe. Even if I use a smart
pointer, I might still inadvertently attempt to dereference a null
pointer. I can create a std::vector<TableRow>, but then I no longer have
polymorphism when I access the elements.
[snip]

Waht about using a smart pointer that ensures the validity of the pointee?


Best

Kai-Uwe Bux
 
A

Axter

Steven said:
I've run into a situation where the conventional thinking doesn't seem
satisfactory. I have a table of data where each row maps into a struct. I
want to put these into a vector. My overall design uses interfaces for
everything accessed from outside of the namespace. I also have a class
that acts as a wrapper for the structs. For example:

struct Row { long _col0; long _col1; };

class TableRow_IF {
public:
virtual long getCol0() const = 0;
virtual long getCol1() const = 0;
virtual ~TableRow_IF(){}
};

using std::istream;

class TableRow: public TableRow_IF {
bool _foreignEndian;
Row _row;

public:

TableRow(istream& in, istream::pos_type pos, bool foreignEndian_){
/*read the row data*/
}

virtual long getCol0() const {
return _foreignEndian? reendian(_row._col0): _row._col0;
}

virtual long getCol1() const {
return _foreignEndian? reendian(_row._col1): _row._col1;
}

virtual ~TableRow_IF(){}
};


That works. All the user needs to know about is TableRow_IF. But now I
want a collection of rows. I can't make a std::vector<TableRow_IF> because
that would require the instantiation of an abstract class. I can make a
std::vector<TableRow_IF*>, but that is less safe. Even if I use a smart
pointer, I might still inadvertently attempt to dereference a null pointer.
I can create a std::vector<TableRow>, but then I no longer have
polymorphism when I access the elements.

What I want is this:

class Table_IF {
// acts like a std::vector<TableRow_IF>, except it copmiles.
virtual TableInfo() const = 0;// information about the table

};

class Table: public Table_IF {
// derive from std::vector<TableRow> ??????
virtual TableInfo() const { return _info; }
//...
};

Is there a standard C++ pattern for addressing this kind of situation?

This may prove to be the best approach for the entire project:
http://www.research.att.com/~bs/matrix.c

I believe it's what I will try now for the situation described above.

--
If our hypothesis is about anything and not about some one or more
particular things, then our deductions constitute mathematics. Thus
mathematics may be defined as the subject in which we never know what we
are talking about, nor whether what we are saying is true.-Bertrand Russell
Consider using a clone_ptr smart pointer.
Check out the following link:
http://www.codeguru.com/Cpp/Cpp/algorithms/general/article.php/c10407/

The clone pointer in the above link works great for a container of
abstract pointers.
 

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

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,904
Latest member
HealthyVisionsCBDPrice

Latest Threads

Top