I inherited from C++ STL container and add my own methods to it. The rationale was such that to the clients, it will look act a regular list, yet has application-specific methods they can readily be called.
This works fine, but I have read numerous posts about not inheriting from STL. Can someone provide a concrete advice of how I might write the code below in a better way?
class Item
{
int a;
int b;
int c;
int SpecialB()
{
return a * b + c;
}
};
class ItemList : public std::vector<Item>
{
int MaxA()
{
if( this->empty() )
throw;
int maxA = (*this)[0].a;
for( int idx = 1; idx < this->size(); idx++ )
{
if( (*this)[idx].a > maxA )
{
maxA = (*this)[idx].a;
}
}
return maxA;
}
int SpecialB()
{
if( this->empty() )
throw;
int specialB = (*this)[0].SpecialB();
for( int idx = 1; idx < this->size(); idx++ )
{
if( (*this)[idx].SpecialB() < specialB )
{
specialB -= (*this)[idx].c;
}
}
return specialB;
}
int AvgC()
{
if( this->empty() )
throw;
int cSum = 0;
for( int idx = 0; idx < this->size(); idx++ )
{
cSum += (*this)[idx].c;
}
return cSum / this->size(); // average
}
};
EDIT: Thanks for a bunch of thoughtful answers. I will create helper functions instead and from now on will never inherit from STL containers.
This is a bad idea.
There are a lot of reasons you shouldn't derive from STL classes, foremost of which is that they're not designed for it. Vector doesn't have a virtual destructor, so if you extend it, the superclass's destructor may not be called properly and you'll get memory leaks.
For more on this, see this answer on why not to derive from std::string
. Many of the same points apply:
Constructor doesn’t work for class inherited from std::string
std::vector
is assignable, but if you add your own fields they won't get copied on assignment if you assign from a vector pointer or vector reference. This is because vector
's operator=
does not know about your fields.For all of these reasons, you're better off making utility functions than extending when it comes to STL.
why you need extend vector in this way?
use standard <algorithm>
with your functors.
e.g.
std::min_element
, std::max_element
int max_a = std::max_element
(
v.begin(),
v.end(),
boost::bind(
std::less< int >(),
bind( &Item::a, _1 ),
bind( &Item::a, _2 )
)
)->a;
std::accumulate
- for calculate avarage
const double avg_c = std::accumulate( v.begin(), v.end(), double( 0 ), boost::bind( Item::c, _1 ) ) / v.size(); // ofcourse check size before divide
your ItemList::SpecialB() could be rewrited as:
int accumulate_func( int start_from, int result, const Item& item )
{
if ( item.SpecialB() < start_from )
{
result -= item.SpecialB();
}
return result;
}
if ( v.empty() )
{
throw sometghing( "empty vector" );
}
const int result = std::accumulate( v.begin(), v.end(), v.front(), boost::bind( &accumulate_func, v.front(), _1, _2 ) );
BTW: if you don't need access to members, you don't need inheritance.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With