c++ - Is it okay to inherit implementation from STL containers, rather than delegate? -
i have class adapts std::vector model container of domain-specific objects. want expose of std::vector api user, he/she may use familiar methods (size, clear, at, etc...) , standard algorithms on container. seems reoccurring pattern me in designs:
class mycontainer : public std::vector<myobject> { public: // redeclare container traits: value_type, iterator, etc... // domain-specific constructors // (more useful user std::vector ones...) // add few domain-specific helper methods... // perhaps modify or hide few methods (domain-related) };
i'm aware of practice of preferring composition inheritance when reusing class implementation -- there's gotta limit! if delegate std::vector, there (by count) 32 forwarding functions!
so questions are... bad inherit implementation in such cases? risks? there safer way can implement without typing? heretic using implementation inheritance? :)
edit:
what making clear user should not use mycontainer via std::vector<> pointer:
// non_api_header_file.h namespace detail { typedef std::vector<myobject> myobjectbase; } // api_header_file.h class mycontainer : public detail::myobjectbase { // ... };
the boost libraries seem stuff time.
edit 2:
one of suggestions use free functions. i'll show here pseudo-code:
typedef std::vector<myobject> mycollection; void specialcollectioninitializer(mycollection& c, arguments...); result specialcollectionfunction(const mycollection& c); etc...
a more oo way of doing it:
typedef std::vector<myobject> mycollection; class mycollectionwrapper { public: // constructor mycollectionwrapper(arguments...) {construct coll_} // access collection directly mycollection& collection() {return coll_;} const mycollection& collection() const {return coll_;} // special domain-related methods result myspecialmethod(arguments...); private: mycollection coll_; // other domain-specific member variables used // in conjunction collection. }
the risk deallocating through pointer base class (delete, delete[], , potentially other deallocation methods). since these classes (deque, map, string, etc.) don't have virtual dtors, it's impossible clean them pointer classes:
struct badexample : vector<int> {}; int main() { vector<int>* p = new badexample(); delete p; // undefined behavior return 0; }
that said, if you're willing make sure never accidentally this, there's little major drawback inheriting them—but in cases that's big if. other drawbacks include clashing implementation specifics , extensions (some of may not use reserved identifiers) , dealing bloated interfaces (string in particular). however, inheritance intended in cases, container adapters stack have protected member c (the underlying container adapt), , it's accessible derived class instance.
instead of either inheritance or composition, consider writing free functions take either iterator pair or container reference, , operate on that. practically of <algorithm> example of this; , make_heap, pop_heap, , push_heap, in particular, example of using free functions instead of domain-specific container.
so, use container classes data types, , still call free functions domain-specific logic. can still achieve modularity using typedef, allows both simplify declaring them , provides single point if part of them needs change:
typedef std::deque<int, myallocator> example; // ... example c (42); example_algorithm(c); example_algorithm2(c.begin() + 5, c.end() - 5); example::iterator i; // nested types easier
notice value_type , allocator can change without affecting later code using typedef, , container can change deque vector.
Comments
Post a Comment