好吧,这真的很难承认,但我确实有一个强烈的诱惑,从std::vector继承。
I need about 10 customized algorithms for vector and I want them to be directly members of the vector. But naturally I want also to have the rest of std::vector's interface. Well, my first idea, as a law-abiding citizen, was to have an std::vector member in MyVector class. But then I would have to manually reprovide all of the std::vector's interface. Too much to type. Next, I thought about private inheritance, so that instead of reproviding methods I would write a bunch of using std::vector::member's in the public section. This is tedious too actually.
在这里,我真的认为我可以简单地从std::vector公开继承,但在文档中提供了一个警告,该类不应该多态地使用。我认为大多数开发人员都有足够的能力来理解这无论如何都不应该多态地使用。
我的决定是绝对不合理的吗?如果有,为什么?你能提供一个替代方案,这将有额外的成员实际上成员,但不会涉及重新键入所有矢量的接口?我很怀疑,但如果你能做到,我会很开心的。
而且,除了有些白痴能写出这样的东西
std::vector<int>* p = new MyVector
使用MyVector还有其他现实的危险吗?通过说现实,我放弃了一些东西,比如想象一个函数,它接受一个指向向量的指针…
我已经陈述了我的观点。我有罪。现在就看你是否原谅我了:)
如果你遵循好的c++风格,缺少虚函数不是问题,而是切片(参见https://stackoverflow.com/a/14461532/877329)
为什么虚函数的缺失不是问题?因为函数不应该尝试删除它接收到的任何指针,因为它没有指针的所有权。因此,如果遵循严格的所有权策略,就不应该需要虚拟析构函数。例如,这总是错误的(有或没有虚析构函数):
void foo(SomeType* obj)
{
if(obj!=nullptr) //The function prototype only makes sense if parameter is optional
{
obj->doStuff();
}
delete obj;
}
class SpecialSomeType:public SomeType
{
// whatever
};
int main()
{
SpecialSomeType obj;
doStuff(&obj); //Will crash here. But caller does not know that
// ...
}
相反,这将始终工作(使用或不使用虚析构函数):
void foo(SomeType* obj)
{
if(obj!=nullptr) //The function prototype only makes sense if parameter is optional
{
obj->doStuff();
}
}
class SpecialSomeType:public SomeType
{
// whatever
};
int main()
{
SpecialSomeType obj;
doStuff(&obj);
// The correct destructor *will* be called here.
}
如果该对象是由工厂创建的,工厂还应该返回一个指向工作删除器的指针,应该使用该指针而不是delete,因为工厂可能使用自己的堆。调用者可以以share_ptr或unique_ptr的形式获取它。简而言之,不要删除不是直接从new中获取的任何内容。
不从std::vector公开继承的主要原因是缺少虚析构函数,这有效地阻止了您多态地使用后代。特别是,你不允许删除std::vector<T>*,它实际上指向一个派生对象(即使派生类没有添加成员),但编译器通常不能警告你。
在这些条件下允许私有继承。因此,我建议使用私有继承并从父方法转发所需的方法,如下所示。
class AdVector: private std::vector<double>
{
typedef double T;
typedef std::vector<double> vector;
public:
using vector::push_back;
using vector::operator[];
using vector::begin;
using vector::end;
AdVector operator*(const AdVector & ) const;
AdVector operator+(const AdVector & ) const;
AdVector();
virtual ~AdVector();
};
您应该首先考虑重构您的算法,以抽象它们所操作的容器类型,并将它们保留为自由模板函数,正如大多数回答者所指出的那样。这通常是通过让算法接受一对迭代器而不是容器作为参数来实现的。