Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 使用C++;继承以增强具有所有权语义的类_C++_Oop_Multiple Inheritance_Unique Ptr_Liskov Substitution Principle - Fatal编程技术网

C++ 使用C++;继承以增强具有所有权语义的类

C++ 使用C++;继承以增强具有所有权语义的类,c++,oop,multiple-inheritance,unique-ptr,liskov-substitution-principle,C++,Oop,Multiple Inheritance,Unique Ptr,Liskov Substitution Principle,我有一些(在我看来)相当具体的所有权要求:我有一个类,它基本上解释一个double数组,这是一种特殊的方式(一些相当大的矩阵的串联),并且希望与一个C库通信,然后用另一种方式解释(一个非常长的数学向量)。在某些情况下,我想解释一个由C库传递给回调的指针,也就是说,它没有所有权。在这种情况下,复制将是非常不切实际的。在其他情况下,我希望自己分配缓冲区,并将其传递给C库。在这种情况下,我的代码拥有缓冲区 我创建了一个“构建块”,将双数组解释为矩阵(使用boost::numeric::ublas::s

我有一些(在我看来)相当具体的所有权要求:我有一个类,它基本上解释一个double数组,这是一种特殊的方式(一些相当大的矩阵的串联),并且希望与一个C库通信,然后用另一种方式解释(一个非常长的数学向量)。在某些情况下,我想解释一个由C库传递给回调的指针,也就是说,它没有所有权。在这种情况下,复制将是非常不切实际的。在其他情况下,我希望自己分配缓冲区,并将其传递给C库。在这种情况下,我的代码拥有缓冲区

我创建了一个“构建块”,将双数组解释为矩阵(使用
boost::numeric::ublas::shallow_array_adapter
,但这基本上是不相关的),如下所示:

class-Foo{
公众:
显式Foo(双*缓冲区);
Foo(const Foo&)=删除;
Foo(Foo&&)=删除;
Foo&运算符=(const Foo&)=删除;
/*一些访问者*/
受保护的:
Foo&operator=(Foo&&)=默认值;
私人:
/*一些将指针存储到缓冲区的东西*/
};
禁止复制和移动,以便不会意外地创建和移动实例或将其移动到超出缓冲区本身的位置。当然,通过直接将指针传递到某个地方,可以有意识地创建这样的实例,但是可以更容易地在源代码中发现

我问题的第一部分:让“
Foo
增强了缓冲区的所有权”成为
Foo
的子类有意义吗

Foo
的每一个操作都可以通过owning-
Foo
实现,此外,owning-
Foo
可以自由复制和移动。闻起来好像满足了利斯科夫替代原理。能够以相同的语法方式处理owning-
Foo
Foo
而无需在owning-
Foo
中编写一系列方法,将委托给成员变量是非常舒服的

另一方面,可能存在-
Foo
的所有者,该所有者处理所有权而不处理其他内容,并且包含可从外部访问的
Foo
实例,从而更好地分离关注点

我实现了owning-
Foo
如下:

class OwningFoo:private std::unique\u ptr,public Foo{
公众:
显式OwningFoo(标准::大小\u t大小)
:std::unique_ptr(新的双[尺寸]),
Foo(std::unique_ptr::get()),size(size){
}
/*复制和移动构造函数的实现以及
*已编辑赋值运算符*/
OwningFoo(const OwningFoo&);
OwningFoo(OwningFoo&&);
OwningFoo&运算符=(const OwningFoo&);
OwningFoo&operator=(OwningFoo&&);
私人:
标准:尺寸;
};
我问题的第二部分:这是多重和私有继承的好例子吗?我是不是在什么地方射中了自己的脚


请注意,如果
Foo
不是成员,则
std::unique_ptr
既不能是成员,因为它需要在
Foo
之前初始化,我这样做的方式是将所有权问题推到更低的位置。Foo有一个缓冲区,并且知道如何在缓冲区被破坏时清理它。例如,std::shared_ptr有一个destroy回调,可用于此目的。这显示了让智能指针知道如何删除此特定实例的公认模式

实际上,您应该有一个可能的共享缓冲区,以便跟踪总所有权。隐式地将它编程为“不是我”,让其他地方知道发生了什么是相当脆弱的

“检查所有权标志”只是“我是最后一个/唯一的所有者”的一个特例,它有一个通用的健壮实现,您可以使用


在您提到的问题中,拥有缓冲区的C代码如何与类的生存期协调?这听起来很糟糕,让你的类知道它不拥有缓冲区(以一种封装良好的方式)并不能改变C代码不知道你的实例何时使用它的问题。

我这样做的方式是将所有权问题推到更深的层次。Foo有一个缓冲区,并且知道如何在缓冲区被破坏时清理它。例如,std::shared_ptr有一个destroy回调,可用于此目的。这显示了让智能指针知道如何删除此特定实例的公认模式

实际上,您应该有一个可能的共享缓冲区,以便跟踪总所有权。隐式地将它编程为“不是我”,让其他地方知道发生了什么是相当脆弱的

“检查所有权标志”只是“我是最后一个/唯一的所有者”的一个特例,它有一个通用的健壮实现,您可以使用


在您提到的问题中,拥有缓冲区的C代码如何与类的生存期协调?这听起来很糟糕,让你的类知道它不拥有缓冲区(以一种很好的封装方式)并不能改变C代码不知道你的实例何时使用它的问题。

这相当复杂,很难理解。我认为你需要保持简单。核心问题是,有时您的数据归代码所有,而有时它归某个外部库所有,对吗?那么,在
Foo
中只添加一个关于所有者是谁的标志,然后析构函数查看该标志并适当地删除(或不删除)怎么样?我认为这不可行。我认为,一个拥有的--
Foo
(或--
Foo
的所有者)是可移动或可复制的,而一个非拥有的--
Foo
则不应该这样,以免它超过它不拥有的缓冲区。由于我的代码由于数学原因(即,它是一个非平凡数学模型的实现)已经令人困惑,因此我希望在编译时尽可能多地检查正确性