By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
446,227 Members | 1,166 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 446,227 IT Pros & Developers. It's quick & easy.

Is it ok to inherit from vector?

P: n/a
Like this.

/********************/
class Card {
public:
Card() : rank(0), suit(0) {}
...
private:
int rank;
int suit;
};

class Cards : public vector<Card> {
public:
Cards();
...
};
/********************/

What about other STL types like string?

Thanks.
Jul 19 '05 #1
Share this Question
Share on Google+
10 Replies


P: n/a
Freddy Flares wrote:
Like this.

/********************/
class Card {
public:
Card() : rank(0), suit(0) {}
...
private:
int rank;
int suit;
};

class Cards : public vector<Card> {
public:
Cards();
...
};
/********************/

What about other STL types like string?


I wouldn't others would - see thread and make your own mind up.
http://groups.google.com/groups?as_u....uni-berlin.de

Jul 19 '05 #2

P: n/a
Freddy Flares wrote:
Like this.

/********************/
class Card {
public:
Card() : rank(0), suit(0) {}
...
private:
int rank;
int suit;
};

class Cards : public vector<Card> {
public:
Cards();
...
};
/********************/

What about other STL types like string?

Yes sure - no problems as long as any vector created with "Cards" is
destroyed from Cards's destructor.

Apart from this, the rest you'll hear is religion.

G

Jul 19 '05 #3

P: n/a
> Yes sure - no problems as long as any vector created with "Cards" is
destroyed from Cards's destructor.

Apart from this, the rest you'll hear is religion.


I agree. People like to quote ad nauseam about the lack of "virtual
destructors" and "concrete" classes (including Stroustrup himself) but it's
bunk no matter what the purists say (and with 20 years in the field I know
what I'm talking about). If done properly it's not a problem.
Jul 19 '05 #4

P: n/a
"Freddy Flares" <a@b.com> wrote in message
news:bo**********@sparta.btinternet.com...
Like this.

/********************/
class Card {
public:
Card() : rank(0), suit(0) {}
...
private:
int rank;
int suit;
};

class Cards : public vector<Card> {
public:
Cards();
...
};
/********************/

What about other STL types like string?

Thanks.


I don't think it's a good idea. Standard containers aren't really designed
to be base classes. I think generally that encapulation is a better paradigm
than inheritance unless you are designing a set of polymorphic classes. The
attractive thing about using inheritance with concrete types is that it can
save you a little typing. But encapsulation is more flexible and
maintainable IMHO.

Of course encapsulation and inheritance can both be a waste of time if your
only purpose is to add some functions. Just use functions! e.g.

typedef std::vector<Card> Deck;

void shuffle(Deck &);
Card deal(Deck &);
const Card& peek(const Deck &);

etc. This is actually a very clean design approach in a lot of cases.

--
Cy
http://home.rochester.rr.com/cyhome/
Jul 19 '05 #5

P: n/a
On Wed, 12 Nov 2003 23:09:07 +0000 (UTC), Freddy Flares wrote:
class Cards : public vector<Card> { What about other STL types like string?


it's legal, but it's also dangerous, which means bad design. You'd
rather use encapsulation or free functions accepting (vector<Card>&)
parameter. Or if you really want to use inheritance, try this:

class Cards : protected vector<Card>{
using vector<Card>::size; // etc.

B.
Jul 19 '05 #6

P: n/a
On Thu, 13 Nov 2003 01:25:42 GMT, "John Brown" <_nospam@_nospam.com>
wrote:
Yes sure - no problems as long as any vector created with "Cards" is
destroyed from Cards's destructor.

Apart from this, the rest you'll hear is religion.


I agree. People like to quote ad nauseam about the lack of "virtual
destructors" and "concrete" classes (including Stroustrup himself) but it's
bunk no matter what the purists say (and with 20 years in the field I know
what I'm talking about). If done properly it's not a problem.


I disagree. I agree that the virtual destructor problem is a minor
thing. However, a much more major thing is the fact that Cards
probably has class invariants that vector<Cards> doesn't. For a start
there should perhaps be a separate Pack class and Hand class. Exposing
the whole vector interface may cause difficult to track down bugs in
the future, unless the Cards class is only used internally.

Deriving from a container is generally a "quick hack" that you end up
having to refactor in the long run anyway.

Tom
Jul 19 '05 #7

P: n/a
> I disagree. I agree that the virtual destructor problem is a minor
thing. However, a much more major thing is the fact that Cards
probably has class invariants that vector<Cards> doesn't. For a start
there should perhaps be a separate Pack class and Hand class. Exposing
the whole vector interface may cause difficult to track down bugs in
the future, unless the Cards class is only used internally.


Actually I agree with you. A restricted interface is typically necessary
though you can employ "using" statements to privatize public base class
members if you want (unbeknownst to many developers though it's an ugly
approach IMO). My real beef lies with those pedantic arguments that state
you absolutely must not do it:

a) Because of the virtual destructor issue
b) Because it's a "concrete" class not intended for further derivation

Well item a isn't an issue if properly controlled and item b is just a
pie-in-the-sky philosophy. Why should someone write a regular (non-member)
"toupper()" function for instance when it's cleaner to derive "MyString"
from "std::string" and implement a member function that does this instead.
It fits naturally into the OOP model and is therefore much cleaner
(especially for strings and vectors which are a staple of most projects).
Therefore, for a generic "vector" class it's ok to derive from it in many
circumstances (to add additional functionality in a controlled environment
for instance). When you need a restricted interface then you can consider
encapsulation.
Jul 19 '05 #8

P: n/a
"John Brown" <_nospam@_nospam.com> wrote in message
news:RT*****************@news04.bloor.is.net.cable .rogers.com...
I disagree. I agree that the virtual destructor problem is a minor
thing. However, a much more major thing is the fact that Cards
probably has class invariants that vector<Cards> doesn't. For a start
there should perhaps be a separate Pack class and Hand class. Exposing
the whole vector interface may cause difficult to track down bugs in
the future, unless the Cards class is only used internally.
Actually I agree with you. A restricted interface is typically necessary
though you can employ "using" statements to privatize public base class
members if you want (unbeknownst to many developers though it's an ugly
approach IMO). My real beef lies with those pedantic arguments that state
you absolutely must not do it:

a) Because of the virtual destructor issue
b) Because it's a "concrete" class not intended for further derivation

Well item a isn't an issue if properly controlled and item b is just a
pie-in-the-sky philosophy. Why should someone write a regular (non-member)
"toupper()" function for instance when it's cleaner to derive "MyString"
from "std::string" and implement a member function that does this instead.


Great. Now you have two versions of std::string floating around which differ
only in that one has a new member function. If I want to use your toupper
function but only have a std::string available I have to convert to a
different class just to use it. If I *don't* want to use your toupper
function I can't just ignore it -- for instance when somebody passes me a
MyString I have to look up what it is. And what if I wan't to add a second
function? Should I make a third string class? You have neatly outlined why
you should never do what you are advising.
It fits naturally into the OOP model and is therefore much cleaner
<groan> If this is your idea of cleanliness I hope you don't cook.
(especially for strings and vectors which are a staple of most projects).
Therefore, for a generic "vector" class it's ok to derive from it in many
circumstances (to add additional functionality in a controlled environment
for instance). When you need a restricted interface then you can consider
encapsulation.


I agree that some writers get carried away with pedantic arguments about
concrete base classes, but I think the rest of your argument is nonsense.

--
Cy
http://home.rochester.rr.com/cyhome/
Jul 19 '05 #9

P: n/a
On Sat, 15 Nov 2003 15:46:57 GMT, John Brown wrote:
It fits naturally into the OOP model and is therefore much cleaner
(especially for strings and vectors which are a staple of most projects).
Therefore, for a generic "vector" class it's ok to derive from it in many


what you advise here is just against OOP. It is called
"strong coupling" and "mixing interface with implementation".
B.

Jul 19 '05 #10

P: n/a
John Brown wrote:
Yes sure - no problems as long as any vector created with "Cards" is
destroyed from Cards's destructor.

Apart from this, the rest you'll hear is religion.

I agree. People like to quote ad nauseam about the lack of "virtual
destructors" and "concrete" classes (including Stroustrup himself) but it's
bunk no matter what the purists say (and with 20 years in the field I know
what I'm talking about). If done properly it's not a problem.


You have to be sure that nobody ever decides to delete your
derived class via a base class pointer. As time goes on the
likelihood is that someone will, then you have undefined
behaviour.

Here is an example that results in segmentation error in
addition to the memory leak, if you uncomment the int b in A.

#include <vector>

class A {
int a;
// int b;
public:
virtual ~A() {};

};

class B : public std::vector<int> {
public:
virtual ~B() {};
};

class C: public A , public B {
public:
};

C* f()
{
new C;
}
int main()
{
std::vector<int>* b = f();
delete b;
return 0;
}

Jul 19 '05 #11

This discussion thread is closed

Replies have been disabled for this discussion.