猿问

从STL容器继承实现而不是委托可以吗?

从STL容器继承实现而不是委托可以吗?

我有一个类来适应std:vectory来建模特定于域的对象的容器。我希望向用户公开大部分STD:VectorAPI,以便他/她可以使用熟悉的方法(大小、清除、at等)。以及容器上的标准算法。在我的设计中,这似乎是一种反复出现的模式:

class MyContainer : public std::vector<MyObject>{public:
   // Redeclare all container traits: value_type, iterator, etc...

   // Domain-specific constructors
   // (more useful to the user than std::vector ones...)

   // Add a few domain-specific helper methods...

   // Perhaps modify or hide a few methods (domain-related)};

我知道在为实现重用类时更喜欢组合而不是继承的做法-但是一定会有限制的!如果我将所有内容委托给std:vectoral,那么就会有32个转发函数!

所以我的问题是.。在这种情况下继承实现真的那么糟糕吗?风险有多大?有没有更安全的方法,我可以实现这一点,而不需要这么多的打字?我是一个使用实现继承的异端者吗?:)

编辑:

如何明确说明用户不应通过std:Vectoral<>指针使用MyContainer:

// non_api_header_file.hnamespace detail{
   typedef std::vector<MyObject> MyObjectBase;}// api_header_file.hclass MyContainer : public detail::MyObjectBase{
   // ...};

Boost库似乎一直在做这件事。

编辑2:

其中一项建议是使用免费功能。我将在这里显示为伪代码:

typedef std::vector<MyObject> MyCollection;void specialCollectionInitializer(MyCollection& c, arguments...);result specialCollectionFunction(const MyCollection& c);etc...

一种更OO的方法:

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 with the c


跃然一笑
浏览 589回答 3
3回答

慕斯王

正如大家已经说过的,STL容器没有虚拟析构函数,因此从它们继承最多是不安全的。我一直认为使用模板进行通用编程是一种不同风格的OO-一种没有继承的OO。算法定义了它们所需的接口。就像鸭型你可以使用静态语言。无论如何,我确实有一些东西要补充到讨论中。我以前创建自己的模板专门化的方法是定义如下类作为基类。template&nbsp;<typename&nbsp;Container>class&nbsp;readonly_container_facade&nbsp;{public: &nbsp;&nbsp;&nbsp;&nbsp;typedef&nbsp;typename&nbsp;Container::size_type&nbsp;size_type; &nbsp;&nbsp;&nbsp;&nbsp;typedef&nbsp;typename&nbsp;Container::const_iterator&nbsp;const_iterator; &nbsp;&nbsp;&nbsp;&nbsp;virtual&nbsp;~readonly_container_facade()&nbsp;{} &nbsp;&nbsp;&nbsp;&nbsp;inline&nbsp;bool&nbsp;empty()&nbsp;const&nbsp;{&nbsp;return&nbsp;container.empty();&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;inline&nbsp;const_iterator&nbsp;begin()&nbsp;const&nbsp;{&nbsp;return&nbsp;container.begin();&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;inline&nbsp;const_iterator&nbsp;end()&nbsp;const&nbsp;{&nbsp;return&nbsp;container.end();&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;inline&nbsp;size_type&nbsp;size()&nbsp;const&nbsp;{&nbsp;return&nbsp;container.size();&nbsp;}protected:&nbsp;//&nbsp;hide&nbsp;to&nbsp;force&nbsp;inherited&nbsp;usage&nbsp;only &nbsp;&nbsp;&nbsp;&nbsp;readonly_container_facade()&nbsp;{}protected:&nbsp;//&nbsp;hide&nbsp;assignment&nbsp;by&nbsp;default &nbsp;&nbsp;&nbsp;&nbsp;readonly_container_facade(readonly_container_facade&nbsp;const&&nbsp;other): &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:&nbsp;container(other.container)&nbsp;{} &nbsp;&nbsp;&nbsp;&nbsp;readonly_container_facade&&nbsp;operator=(readonly_container_facade&&nbsp;other)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;container&nbsp;=&nbsp;other.container; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;*this; &nbsp;&nbsp;&nbsp;&nbsp;}protected: &nbsp;&nbsp;&nbsp;&nbsp;Container&nbsp;container;};template&nbsp;<typename&nbsp;Container>class&nbsp;writable_container_facade:&nbsp;public&nbsp;readable_container_facade<Container>&nbsp;{public: &nbsp;&nbsp;&nbsp;&nbsp;typedef&nbsp;typename&nbsp;Container::iterator&nbsp;iterator; &nbsp;&nbsp;&nbsp;&nbsp;writable_container_facade(writable_container_facade&&nbsp;other) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;readonly_container_facade(other)&nbsp;{} &nbsp;&nbsp;&nbsp;&nbsp;virtual&nbsp;~writable_container_facade()&nbsp;{} &nbsp;&nbsp;&nbsp;&nbsp;inline&nbsp;iterator&nbsp;begin()&nbsp;{&nbsp;return&nbsp;container.begin();&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;inline&nbsp;iterator&nbsp;end()&nbsp;{&nbsp;return&nbsp;container.end();&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;writable_container_facade&&nbsp;operator=(writable_container_facade&&nbsp;other)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;readable_container_facade<Container>::operator=(other); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;*this; &nbsp;&nbsp;&nbsp;&nbsp;}};这些类公开与STL容器相同的接口。我确实喜欢将修改操作和非修改操作分离为不同的基类的效果。这对康斯特正确性有很好的影响。一个缺点是,如果要将接口与关联容器一起使用,就必须扩展接口。不过,我还没有遇到这种需要。
随时随地看视频慕课网APP
我要回答