Meh*_*dad 5 c++ inheritance stl
我一再读到,从STL容器继承是一件坏事.
(我知道这背后的原因是什么,这不是我的问题.)
牢记上述内容,扩展容器功能的正确方法是什么?
例如,如果我想要一个类似vector
容器,当参数大于或等于容器的大小时自动调整operator[]
大小,我该怎么办?
对我来说,C++ 11中最明显的解决方案是:
template<class T, class A = std::allocator<T> >
class auto_vector : public std::vector<T, A>
{
typedef std::vector<T, A> base_type;
public:
using base_type::vector;
typename base_type::reference operator[](typename base_type::size_type n)
// I don't need const version, so I'll just ignore it here
{
if (n >= this->base_type::size())
{ this->base_type::resize(n + 1); }
return this->base_type::operator[](n);
}
};
Run Code Online (Sandbox Code Playgroud)
在C++ 03中,它将是:
template<class T, class A = std::allocator<T> >
class auto_vector : public std::vector<T, A>
{
typedef std::vector<T, A> base_type;
public:
explicit auto_vector(
typename base_type::allocator_type const &alloc =
typename base_type::allocator_type())
: base_type(alloc) { }
explicit auto_vector(
typename base_type::size_type n,
value_type const &val = value_type(),
typename base_type::allocator_type const &alloc =
typename base_type::allocator_type())
: base_type(n, val, alloc) { }
template<class InIt>
auto_vector(InIt f, InIt l, typename base_type::allocator_type const &alloc =
typename base_type::allocator_type())
: base_type(f, l, alloc) { }
auto_vector(auto_vector const &v) : base_type(v) { }
typename base_type::reference operator[](typename base_type::size_type n)
// I don't need const version
{
if (n >= this->base_type::size())
{ this->base_type::resize(n + 1); }
return this->base_type::operator[](n);
}
};
Run Code Online (Sandbox Code Playgroud)
这两个都是不好的做法,因为他们继承了std::vector
.
首先,关于……
“我多次读到从 STL 容器继承是一件坏事。”
…参考文献提供了 STL 容器没有虚拟析构函数的原因。
对于新手来说,不要从没有虚拟析构函数的类中派生,这当然是个好建议。这使他们无法访问 中的受保护成员std::stack
,使他们无法使用 Microsoft COM 技术等,但总而言之,对于新手来说,网络优势是巨大的。同样,我们建议新手不要使用原始数组和直接new
and delete
,遵循这对新手来说可能是一个巨大的净优势,但是,一些更有经验的人仍然必须这样做,必须实现新手的抽象(理想情况下) ) 限制使用,以免任何 C++ 程序中都没有动态分配。
因此,像这样的类std::stack
清楚地表明关于此的绝对规则是无稽之谈,经验丰富的程序员必须权衡利弊,并且在决定继承时,必须在 和 继承之间public
进行protected
选择private
。
缺点公共继承:如果新手auto_vector
动态分配 ,然后尝试通过使用delete
指向 的指针来销毁它std::vector
,那么设计就无法指导新手正确使用。所以如果是强烈引导新手正确使用的目标,那么要么不这样做,要么也添加让新手难以动态分配的功能。例如,添加一个operator new
具有不可访问类型的附加参数,或者其本身不可访问。
对于当前的情况,其他多态访问 asstd::vector
不是问题,因为索引 astd::vector
超出其大小的代码已经具有未定义的行为。
对于其他情况,人们可以想象的情况,与OP的情况不同,必须考虑这些其他情况的细节:一般的绝对规则在编程中不起作用(好吧,至少在C++编程中不起作用)。
在这种情况下,支持公共继承:这是“我想要所有基类的功能”的最简单、最直接、最清晰的表达。