【发布时间】:2014-03-02 04:05:03
【问题描述】:
我在这个论坛上被告知,我在书上看过,还有其他answers说继承STL容器永远不会好,因为STL容器析构函数不是虚拟的(删除时未定义的行为通过基类指针派生的对象)。
但是,C++11 标准现在允许在编译时使用成员函数说明符(如 delete)进行按合同设计的检查。我完全可以理解为什么继承一个 STL 容器的目的是扩展一两个成员函数更好地替换为将成员函数编码为算法。不过,我有一种情况,我将一组元素建模为一个概念,而元素本身就是其他元素的容器。我需要实现访问子元素数据前向迭代器的双向迭代器(例如 Collection::sub_element_iterator)。在这种情况下,使用组合迫使我重新键入(调整)整个 std::vector 公共接口,只是用迭代器扩展这个新 Collection。
如果我仍然使用继承并以下列方式防止堆分配,在这种情况下是否可以?
这是一个小模型:
#include <vector>
class not_heap_allocable
{
public:
void* operator new (std::size_t count) = delete;
};
template
<
typename Type,
template <typename T> class Allocator = std::allocator
>
class extended_vector
:
public std::vector<Type, Allocator<Type>>,
public not_heap_allocable
{
public:
typedef std::vector<Type> BaseType;
using BaseType::BaseType;
};
using namespace std;
int main(int argc, const char *argv[])
{
vector<int>* vNew = new extended_vector<int> ({0,1,2,3,4,5}); // Compile time error.
return 0;
}
这会导致编译时错误:
main.cpp: In function ‘int main(int, const char**)’:
main.cpp:31:64: error: use of deleted function ‘static void* not_heap_allocable::operator new(std::size_t)’
vector<int>* vNew = new extended_vector<int> ({0,1,2,3,4,5}); // Compile time error.
^
main.cpp:6:15: error: declared here
void* operator new (std::size_t count) = delete;
因此,extended_vector 不再指望人类不要滥用它。
【问题讨论】:
-
我猜你想继承
std::vector<Type, Allocator>,而不是std::vector<Type>? -
@leemes,谢谢,是的!我更正了。
-
我忍不住,但那味道。
-
禁止堆分配并不能清楚地表达意图恕我直言(使用非虚拟 dtor,在堆上创建派生类的对象仍然有效,只是不能通过基类指针)。另一种可能性是使用
private(或protected)继承并通过using-declarations 重新发布成员函数。 -
not_heap_allocable也禁止 放置新...还要注意extended_vector在堆栈上不是必需的(如果它是其他类的一部分)。跨度>
标签: c++ inheritance stl