我有一些(在我看来)相当具体的所有权要求:我有一个类,基本上解释一个双精度数组是一种特定的方式(一些相当大矩阵),并且希望与以另一种方式解释(一个非常长的数学向量)的C库进行通信。在某些情况下,我想解释一个由C库传递给回调函数的指针,也就是说,不需要拥有所有权。在这种情况下,复制将是非常不切实际的。在其他情况下,我想自己分配缓冲区,并将它自己传递给C库。在那种情况下,我的代码拥有缓冲区。使用C++继承来增强拥有所有权语义的类
我创建的“积木”,其解释双阵列作为矩阵(与boost::numeric::ublas::shallow_array_adaptor
,但这大多是不相关的),这样的:
class Foo {
public:
explicit Foo(double *buffer);
Foo(const Foo &) = delete;
Foo(Foo &&) = delete;
Foo &operator=(const Foo &) = delete;
/* Some accessors. */
protected:
Foo &operator=(Foo &&) = default;
private:
/* Some things that store pointers into the buffer. */
};
复制和移动是被禁止的,以便与实例不能意外地被创建或移动到超过缓冲区本身的地方。当然,通过直接将指针传递到某个地方,但可以更容易地在源代码中发现,故意创建这些实例是可能的。
我的问题的第一部分:是否有意义让“Foo
增强与缓冲区的所有权”是Foo
的子类?
的Foo
每个操作是可能的owning- Foo
,另外,owning- Foo
可以自由复制和移动。它闻起来像Liskov替代原则是满意的。能够以相同的方式处理拥有 - Foo
和Foo
句法上没有编写一组方法拥有 - Foo
委托给一个成员变量非常舒服舒适。
另一方面,可能会有所有者 - Foo
,而不是处理所有权,而是包含可从外部访问的Foo
实例,从而更好地分离关注点。
我实现owning- Foo
这样的:
class OwningFoo : private std::unique_ptr<double[]>, public Foo {
public:
explicit OwningFoo(std::size_t size)
: std::unique_ptr<double[]>(new double[size]),
Foo(std::unique_ptr<double[]>::get()), size_(size) {
}
/* Implementation of copy and move constructors and
* assignment operators redacted. */
OwningFoo(const OwningFoo &);
OwningFoo(OwningFoo &&);
OwningFoo &operator=(const OwningFoo &);
OwningFoo &operator=(OwningFoo &&);
private:
std::size_t size_;
};
我的,我的问题的第二部分:这是一个多与私有继承一个很好的例子?我是否在某处拍摄自己的脚?
注意,如果Foo
是不是会员,比std::unique_ptr
既不能成为会员,因为它需要Foo
之前initilized 。
这是相当复杂和难以遵循恕我直导。我认为你需要保持简单。核心问题是,有时候你的代码拥有数据,有时候它是由某个外部库拥有的,对吗?那么,如何在Foo中标记一个关于谁是所有者的标志,并且析构函数会查看标志并适当地删除(或不)。 –
嗯,我不认为这可行。拥有的'Foo'(或者''Foo''的拥有者)是可移动的或可复制的,而我认为非拥有的''Foo'不应该是这样,以免它超过它不拥有的缓冲区。由于事实上我的代码已经因*数学*原因而混淆(即它是一个非平凡数学模型的实现),我想在编译时检查尽可能多的正确性,因为它实际上是可能的。 –
如果您想在编译时检查数学正确性,请使用函数式语言。 C语言是为编写操作系统的明确目的而发明的,C++尽管增加了许多像OOP这样的花哨的东西,但非常遵循相同的设计原则。如果你在做数学,使用一种非常适合数学的语言,比如Haskell或者Scala。您可能会失去一些运行时间性能,但您可以获得开发时间效率和编译时正确性检查。 –