Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/131.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++ “std::shared_from_this”不能由其派生类继承吗?_C++_Shared Ptr_Smart Pointers - Fatal编程技术网

C++ “std::shared_from_this”不能由其派生类继承吗?

C++ “std::shared_from_this”不能由其派生类继承吗?,c++,shared-ptr,smart-pointers,C++,Shared Ptr,Smart Pointers,std::shared\u不能从它的派生类继承吗 为什么这个代码段不进行编译检查?我已经仔细阅读了文档,但仍然找不到任何线索。我想了很久了。如果能在这个问题上得到一些帮助,我将不胜感激 以下是未编译的代码段: // enable_shared_from_this example #include <iostream> #include <memory> struct C : std::enable_shared_from_this<C> {}; struc

std::shared\u不能从它的派生类继承吗

为什么这个代码段不进行编译检查?我已经仔细阅读了文档,但仍然找不到任何线索。我想了很久了。如果能在这个问题上得到一些帮助,我将不胜感激

以下是未编译的代码段:

// enable_shared_from_this example
#include <iostream>
#include <memory>

struct C : std::enable_shared_from_this<C> {};

struct D : public C {};

int main () {
  std::shared_ptr<D> foo, bar;

  foo = std::make_shared<D>();

  bar = foo->shared_from_this();


  return 0;
}
编译器抱怨:

In file included from /usr/include/c++/4.9/bits/shared_ptr.h:52:0,
                 from /usr/include/c++/4.9/memory:82,
                 from 3:
/usr/include/c++/4.9/bits/shared_ptr_base.h: In instantiation of 'std::__shared_ptr<_Tp, _Lp>& std::__shared_ptr<_Tp, _Lp>::operator=(std::__shared_ptr<_Tp1, _Lp>&&) [with _Tp1 = C; _Tp = D; __gnu_cxx::_Lock_policy _Lp = (__gnu_cxx::_Lock_policy)2u]':
/usr/include/c++/4.9/bits/shared_ptr.h:299:4:   required from 'std::shared_ptr<_Tp>& std::shared_ptr<_Tp>::operator=(std::shared_ptr<_Tp1>&&) [with _Tp1 = C; _Tp = D]'
14:7:   required from here
/usr/include/c++/4.9/bits/shared_ptr_base.h:1001:4: error: no matching function for call to 'std::__shared_ptr<D, (__gnu_cxx::_Lock_policy)2u>::__shared_ptr(std::remove_reference<std::__shared_ptr<C, (__gnu_cxx::_Lock_policy)2u>&>::type)'
    __shared_ptr(std::move(__r)).swap(*this);
    ^
/usr/include/c++/4.9/bits/shared_ptr_base.h:1001:4: note: candidates are:
/usr/include/c++/4.9/bits/shared_ptr_base.h:1145:7: note: std::__shared_ptr<_Tp, _Lp>::__shared_ptr(const std::__weak_ptr<_Tp, _Lp>&, std::nothrow_t) [with _Tp = D; __gnu_cxx::_Lock_policy _Lp = (__gnu_cxx::_Lock_policy)2u]
       __shared_ptr(const __weak_ptr<_Tp, _Lp>& __r, std::nothrow_t)
       ^
/usr/include/c++/4.9/bits/shared_ptr_base.h:1145:7: note:   candidate expects 2 arguments, 1 provided
/usr/include/c++/4.9/bits/shared_ptr_base.h:1087:2: note: template<class _Alloc, class ... _Args> std::__shared_ptr<_Tp, _Lp>::__shared_ptr(std::_Sp_make_shared_tag, const _Alloc&, _Args&& ...)
  __shared_ptr(_Sp_make_shared_tag __tag, const _Alloc& __a,
  ^
/usr/include/c++/4.9/bits/shared_ptr_base.h:1087:2: note:   template argument deduction/substitution failed:
/usr/include/c++/4.9/bits/shared_ptr_base.h:1001:4: note:   cannot convert 'std::move<std::__shared_ptr<C, (__gnu_cxx::_Lock_policy)2u>&>((* & __r))' (type 'std::remove_reference<std::__shared_ptr<C, (__gnu_cxx::_Lock_policy)2u>&>::type {aka std::__shared_ptr<C, (__gnu_cxx::_Lock_policy)2u>}') to type 'std::_Sp_make_shared_tag'
    __shared_ptr(std::move(__r)).swap(*this);
    ^
/usr/include/c++/4.9/bits/shared_ptr_base.h:967:17: note: constexpr std::__shared_ptr<_Tp, _Lp>::__shared_ptr(std::nullptr_t) [with _Tp = D; __gnu_cxx::_Lock_policy _Lp = (__gnu_cxx::_Lock_policy)2u; std::nullptr_t = std::nullptr_t]
       constexpr __shared_ptr(nullptr_t) noexcept
                 ^
/usr/include/c++/4.9/bits/shared_ptr_base.h:967:17: note:   no known conversion for argument 1 from 'std::remove_reference<std::__shared_ptr<C, (__gnu_cxx::_Lock_policy)2u>&>::type {aka std::__shared_ptr<C, (__gnu_cxx::_Lock_policy)2u>}' to 'std::nullptr_t'
/usr/include/c++/4.9/bits/shared_ptr_base.h:963:2: note: template<class _Tp1> std::__shared_ptr<_Tp, _Lp>::__shared_ptr(std::auto_ptr<_Up>&&)
  __shared_ptr(std::auto_ptr<_Tp1>&& __r);
  ^
/usr/include/c++/4.9/bits/shared_ptr_base.h:963:2: note:   template argument deduction/substitution failed:
/usr/include/c++/4.9/bits/shared_ptr_base.h:1001:4: note:   'std::remove_reference<std::__shared_ptr<C, (__gnu_cxx::_Lock_policy)2u>&>::type {aka std::__shared_ptr<C, (__gnu_cxx::_Lock_policy)2u>}' is not derived from 'std::auto_ptr<_Up>'
    __shared_ptr(std::move(__r)).swap(*this);
    ^
/usr/include/c++/4.9/bits/shared_ptr_base.h:951:2: note: template<class _Tp1, class _Del> std::__shared_ptr<_Tp, _Lp>::__shared_ptr(std::unique_ptr<_Up, _Ep>&&)
  __shared_ptr(std::unique_ptr<_Tp1, _Del>&& __r)
  ^
/usr/include/c++/4.9/bits/shared_ptr_base.h:951:2: note:   template argument deduction/substitution failed:
/usr/include/c++/4.9/bits/shared_ptr_base.h:1001:4: note:   'std::remove_reference<std::__shared_ptr<C, (__gnu_cxx::_Lock_policy)2u>&>::type {aka std::__shared_ptr<C, (__gnu_cxx::_Lock_policy)2u>}' is not derived from 'std::unique_ptr<_Tp, _Dp>'
    __shared_ptr(std::move(__r)).swap(*this);
    ^
/usr/include/c++/4.9/bits/shared_ptr_base.h:939:11: note: template<class _Tp1> std::__shared_ptr<_Tp, _Lp>::__shared_ptr(const std::__weak_ptr<_Tp1, _Lp>&)
  explicit __shared_ptr(const __weak_ptr<_Tp1, _Lp>& __r)
           ^
/usr/include/c++/4.9/bits/shared_ptr_base.h:939:11: note:   template argument deduction/substitution failed:
/usr/include/c++/4.9/bits/shared_ptr_base.h:1001:4: note:   'std::remove_reference<std::__shared_ptr<C, (__gnu_cxx::_Lock_policy)2u>&>::type {aka std::__shared_ptr<C, (__gnu_cxx::_Lock_policy)2u>}' is not derived from 'const std::__weak_ptr<_Tp>'
    __shared_ptr(std::move(__r)).swap(*this);
    ^
/usr/include/c++/4.9/bits/shared_ptr_base.h:931:2: note: template<class _Tp1, class> std::__shared_ptr<_Tp, _Lp>::__shared_ptr(std::__shared_ptr<_Tp1, _Lp>&&)
  __shared_ptr(__shared_ptr<_Tp1, _Lp>&& __r) noexcept
  ^
/usr/include/c++/4.9/bits/shared_ptr_base.h:931:2: note:   template argument deduction/substitution failed:
/usr/include/c++/4.9/bits/shared_ptr_base.h:929:31: error: no type named 'type' in 'struct std::enable_if<false, void>'
       template<typename _Tp1, typename = typename
                               ^
/usr/include/c++/4.9/bits/shared_ptr_base.h:922:7: note: std::__shared_ptr<_Tp, _Lp>::__shared_ptr(std::__shared_ptr<_Tp, _Lp>&&) [with _Tp = D; __gnu_cxx::_Lock_policy _Lp = (__gnu_cxx::_Lock_policy)2u]
       __shared_ptr(__shared_ptr&& __r) noexcept
       ^
/usr/include/c++/4.9/bits/shared_ptr_base.h:922:7: note:   no known conversion for argument 1 from 'std::remove_reference<std::__shared_ptr<C, (__gnu_cxx::_Lock_policy)2u>&>::type {aka std::__shared_ptr<C, (__gnu_cxx::_Lock_policy)2u>}' to 'std::__shared_ptr<D, (__gnu_cxx::_Lock_policy)2u>&&'
/usr/include/c++/4.9/bits/shared_ptr_base.h:918:2: note: template<class _Tp1, class> std::__shared_ptr<_Tp, _Lp>::__shared_ptr(const std::__shared_ptr<_Tp1, _Lp>&)
  __shared_ptr(const __shared_ptr<_Tp1, _Lp>& __r) noexcept
  ^
/usr/include/c++/4.9/bits/shared_ptr_base.h:918:2: note:   template argument deduction/substitution failed:
/usr/include/c++/4.9/bits/shared_ptr_base.h:916:31: error: no type named 'type' in 'struct std::enable_if<false, void>'
       template<typename _Tp1, typename = typename
                               ^
/usr/include/c++/4.9/bits/shared_ptr_base.h:912:7: note: std::__shared_ptr<_Tp, _Lp>::__shared_ptr(const std::__shared_ptr<_Tp, _Lp>&) [with _Tp = D; __gnu_cxx::_Lock_policy _Lp = (__gnu_cxx::_Lock_policy)2u]
       __shared_ptr(const __shared_ptr&) noexcept = default;
       ^
/usr/include/c++/4.9/bits/shared_ptr_base.h:912:7: note:   no known conversion for argument 1 from 'std::remove_reference<std::__shared_ptr<C, (__gnu_cxx::_Lock_policy)2u>&>::type {aka std::__shared_ptr<C, (__gnu_cxx::_Lock_policy)2u>}' to 'const std::__shared_ptr<D, (__gnu_cxx::_Lock_policy)2u>&'
/usr/include/c++/4.9/bits/shared_ptr_base.h:908:2: note: template<class _Tp1> std::__shared_ptr<_Tp, _Lp>::__shared_ptr(const std::__shared_ptr<_Tp1, _Lp>&, _Tp*)
  __shared_ptr(const __shared_ptr<_Tp1, _Lp>& __r, _Tp* __p) noexcept
  ^
/usr/include/c++/4.9/bits/shared_ptr_base.h:908:2: note:   template argument deduction/substitution failed:
/usr/include/c++/4.9/bits/shared_ptr_base.h:1001:4: note:   candidate expects 2 arguments, 1 provided
    __shared_ptr(std::move(__r)).swap(*this);
    ^
/usr/include/c++/4.9/bits/shared_ptr_base.h:903:9: note: template<class _Deleter, class _Alloc> std::__shared_ptr<_Tp, _Lp>::__shared_ptr(std::nullptr_t, _Deleter, _Alloc)
         __shared_ptr(nullptr_t __p, _Deleter __d, _Alloc __a)
         ^
/usr/include/c++/4.9/bits/shared_ptr_base.h:903:9: note:   template argument deduction/substitution failed:
/usr/include/c++/4.9/bits/shared_ptr_base.h:1001:4: note:   cannot convert 'std::move<std::__shared_ptr<C, (__gnu_cxx::_Lock_policy)2u>&>((* & __r))' (type 'std::remove_reference<std::__shared_ptr<C, (__gnu_cxx::_Lock_policy)2u>&>::type {aka std::__shared_ptr<C, (__gnu_cxx::_Lock_policy)2u>}') to type 'std::nullptr_t'
    __shared_ptr(std::move(__r)).swap(*this);
    ^
/usr/include/c++/4.9/bits/shared_ptr_base.h:898:2: note: template<class _Deleter> std::__shared_ptr<_Tp, _Lp>::__shared_ptr(std::nullptr_t, _Deleter)
  __shared_ptr(nullptr_t __p, _Deleter __d)
  ^
/usr/include/c++/4.9/bits/shared_ptr_base.h:898:2: note:   template argument deduction/substitution failed:
/usr/include/c++/4.9/bits/shared_ptr_base.h:1001:4: note:   cannot convert 'std::move<std::__shared_ptr<C, (__gnu_cxx::_Lock_policy)2u>&>((* & __r))' (type 'std::remove_reference<std::__shared_ptr<C, (__gnu_cxx::_Lock_policy)2u>&>::type {aka std::__shared_ptr<C, (__gnu_cxx::_Lock_policy)2u>}') to type 'std::nullptr_t'
    __shared_ptr(std::move(__r)).swap(*this);
    ^
/usr/include/c++/4.9/bits/shared_ptr_base.h:889:2: note: template<class _Tp1, class _Deleter, class _Alloc> std::__shared_ptr<_Tp, _Lp>::__shared_ptr(_Tp1*, _Deleter, _Alloc)
  __shared_ptr(_Tp1* __p, _Deleter __d, _Alloc __a)
  ^
/usr/include/c++/4.9/bits/shared_ptr_base.h:889:2: note:   template argument deduction/substitution failed:
/usr/include/c++/4.9/bits/shared_ptr_base.h:1001:4: note:   mismatched types '_Tp1*' and 'std::__shared_ptr<C, (__gnu_cxx::_Lock_policy)2u>'
    __shared_ptr(std::move(__r)).swap(*this);
    ^
/usr/include/c++/4.9/bits/shared_ptr_base.h:880:2: note: template<class _Tp1, class _Deleter> std::__shared_ptr<_Tp, _Lp>::__shared_ptr(_Tp1*, _Deleter)
  __shared_ptr(_Tp1* __p, _Deleter __d)
  ^
/usr/include/c++/4.9/bits/shared_ptr_base.h:880:2: note:   template argument deduction/substitution failed:
/usr/include/c++/4.9/bits/shared_ptr_base.h:1001:4: note:   mismatched types '_Tp1*' and 'std::__shared_ptr<C, (__gnu_cxx::_Lock_policy)2u>'
    __shared_ptr(std::move(__r)).swap(*this);
    ^
/usr/include/c++/4.9/bits/shared_ptr_base.h:870:11: note: template<class _Tp1> std::__shared_ptr<_Tp, _Lp>::__shared_ptr(_Tp1*)
  explicit __shared_ptr(_Tp1* __p)
           ^
/usr/include/c++/4.9/bits/shared_ptr_base.h:870:11: note:   template argument deduction/substitution failed:
/usr/include/c++/4.9/bits/shared_ptr_base.h:1001:4: note:   mismatched types '_Tp1*' and 'std::__shared_ptr<C, (__gnu_cxx::_Lock_policy)2u>'
    __shared_ptr(std::move(__r)).swap(*this);
    ^
/usr/include/c++/4.9/bits/shared_ptr_base.h:865:17: note: constexpr std::__shared_ptr<_Tp, _Lp>::__shared_ptr() [with _Tp = D; __gnu_cxx::_Lock_policy _Lp = (__gnu_cxx::_Lock_policy)2u]
       constexpr __shared_ptr() noexcept
                 ^
/usr/include/c++/4.9/bits/shared_ptr_base.h:865:17: note:   candidate expects 0 arguments, 1 provided
它是继承的:

// enable_shared_from_this example
#include <iostream>
#include <memory>

struct C : std::enable_shared_from_this<C> {};

struct D : public C {};

int main () {
  std::shared_ptr<D> foo;

  foo = std::make_shared<D>();

  std::shared_ptr<C> bar = foo->shared_from_this();

  return 0;
}
您可以在类C:中从这个定义共享的,因此对象返回std::shated\u ptr。不足为奇。您仍然可以使用std::dynamic\u pointer\u cast将其向下转换为std::shared\u ptr。

它是继承的:

// enable_shared_from_this example
#include <iostream>
#include <memory>

struct C : std::enable_shared_from_this<C> {};

struct D : public C {};

int main () {
  std::shared_ptr<D> foo;

  foo = std::make_shared<D>();

  std::shared_ptr<C> bar = foo->shared_from_this();

  return 0;
}

您可以在类C:中从这个定义共享的,因此对象返回std::shated\u ptr。不足为奇。您仍然可以使用std::dynamic_pointer_cast将其向下转换为std::shared_ptr。

正如@DimityKuzminov已经指出的,shared_from_当从std::shared_ptr调用时,它将始终返回std::shared_指针。为了使用std::dynmaic\u pointer\u cast,您的基还需要有一个类似于虚拟析构函数的虚拟函数,否则编译器会告诉您源类型不是多态的。以下是一个例子:

// enable_shared_from_this example
#include <iostream>
#include <memory>

struct C : std::enable_shared_from_this<C> {
    virtual ~C() = default;
};

template<typename T, typename U>
std::shared_ptr<T> 
shared_from(const std::shared_ptr<U> &a)
{
    return std::dynamic_pointer_cast<T>(a->shared_from_this());
}

struct D : public C {};

int main () {
  std::shared_ptr<D> foo, bar;

  foo = std::make_shared<D>();

  bar = shared_from<D>(foo);

  return 0;
}

正如@DimityKuzminov已经指出的,shared_from_当从std::shared_ptr调用时,它将始终返回std::shared_指针。为了使用std::dynmaic\u pointer\u cast,您的基还需要有一个类似于虚拟析构函数的虚拟函数,否则编译器会告诉您源类型不是多态的。以下是一个例子:

// enable_shared_from_this example
#include <iostream>
#include <memory>

struct C : std::enable_shared_from_this<C> {
    virtual ~C() = default;
};

template<typename T, typename U>
std::shared_ptr<T> 
shared_from(const std::shared_ptr<U> &a)
{
    return std::dynamic_pointer_cast<T>(a->shared_from_this());
}

struct D : public C {};

int main () {
  std::shared_ptr<D> foo, bar;

  foo = std::make_shared<D>();

  bar = shared_from<D>(foo);

  return 0;
}

非常感谢。为什么std::shared_from_不能像普通类那样继承它?例如:类基类{public:void*ptr;};类驱动:公共基{};int main{Drived d;d->ptr=NULL}。我想知道是什么原因导致它有点奇怪。std::enable_shared_这是继承的。如果结构D从C继承了std::enable_shared_,那么D::shared_从C继承了std::enable_shared_,所以它将构造C。如果你想让D::shared_from_this返回D,你必须从std::enable_shared_,从_this继承。@KamilCuk,我明白了。谢谢你的澄清。还有一个问题,因为foo和bar都是左值,理论上我可以得到它们的地址,但是&bar和&foo不起作用。它们得到的是类D的新实例化的地址。我如何得到foo本身的地址呢?类可以重载操作符&,但std::shared_ptr不应该。您可以使用std::addressof来真正获取变量的地址。谢谢。为什么std::shared_from_不能像普通类那样继承它?例如:类基类{public:void*ptr;};类驱动:公共基{};int main{Drived d;d->ptr=NULL}。我想知道是什么原因导致它有点奇怪。std::enable_shared_这是继承的。如果结构D从C继承了std::enable_shared_,那么D::shared_从C继承了std::enable_shared_,所以它将构造C。如果你想让D::shared_from_this返回D,你必须从std::enable_shared_,从_this继承。@KamilCuk,我明白了。谢谢你的澄清。还有一个问题,因为foo和bar都是左值,理论上我可以得到它们的地址,但是&bar和&foo不起作用。它们得到的是类D的新实例化的地址。我如何得到foo本身的地址呢?类可以重载操作符&,但std::shared_ptr不应该。您可以使用std::addressof来真正获取变量的地址。谢谢,评论不错。然而,任何虚函数都足够了,可能没有虚析构函数。是的,你是对的。我将进行编辑。@DmitryKuzminov&StefanKssmr我想知道为什么可能没有虚拟析构函数?我确实看过很多次。我错在哪里?@John,你可以定义一个虚拟析构函数、常规的非虚拟析构函数或者有一个默认析构函数:如果构造正确,每个选项都可以与智能指针一起工作。如果不使用智能指针或使用类型擦除构造共享的ptr,则需要虚拟析构函数。但是要使用动态类型转换,您需要基类中的任何虚拟函数。@John确实,您经常看到它们,但是从类派生不需要虚拟析构函数。这可能会让你感兴趣。谢谢,评论不错。然而,任何虚函数都足够了,可能没有虚析构函数。是的,你是对的。我将进行编辑。@DmitryKuzminov&StefanKssmr我想知道为什么可能没有虚拟析构函数?我确实看过很多次。我错在哪里?@John,你可以定义一个虚拟析构函数、常规的非虚拟析构函数或者有一个默认析构函数:如果构造正确,每个选项都可以与智能指针一起工作。如果不使用智能指针或使用类型擦除构造共享的ptr,则需要虚拟析构函数。但是要使用动态类型转换,您需要基类中的任何虚拟函数。@John确实,您经常看到它们,但是从类派生不需要虚拟析构函数。这可能会让你感兴趣。