Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/fsharp/3.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++中我们可以这样做: struct Base { virtual Base* Clone() const { ... } virtual ~Base(){} }; struct Derived : Base { virtual Derived* Clone() const {...} //overrides Base::Clone };_C++_Smart Pointers_Virtual Functions_Return Type - Fatal编程技术网

带智能指针的返回类型协方差 C++中我们可以这样做: struct Base { virtual Base* Clone() const { ... } virtual ~Base(){} }; struct Derived : Base { virtual Derived* Clone() const {...} //overrides Base::Clone };

带智能指针的返回类型协方差 C++中我们可以这样做: struct Base { virtual Base* Clone() const { ... } virtual ~Base(){} }; struct Derived : Base { virtual Derived* Clone() const {...} //overrides Base::Clone };,c++,smart-pointers,virtual-functions,return-type,C++,Smart Pointers,Virtual Functions,Return Type,但是,以下操作不会达到相同的效果: struct Base { virtual shared_ptr<Base> Clone() const { ... } virtual ~Base(){} }; struct Derived : Base { virtual shared_ptr<Derived> Clone() const {...} //hides Base::Clone }; struct Base { 虚拟共享\u ptr Clone()

但是,以下操作不会达到相同的效果:

struct Base
{
   virtual shared_ptr<Base> Clone() const { ... }
   virtual ~Base(){}
};

struct Derived : Base
{
   virtual shared_ptr<Derived> Clone() const {...} //hides Base::Clone
};
struct Base
{
虚拟共享\u ptr Clone()常量{…}
虚拟~Base(){}
};
派生结构:基
{
虚拟共享\u ptr Clone()常量{…}//隐藏Base::Clone
};
在本例中,
Derived::Clone
隐藏而不是重写它,因为标准规定重写成员的返回类型只能从reference(或pointer)更改为Base to reference(或pointer)再更改为Derived。有什么聪明的解决办法吗?当然,有人可能会说,
Clone
函数无论如何都应该返回一个普通指针,但现在我们先忘掉它吧——这只是一个示例。我正在寻找一种方法,可以将虚拟函数的返回类型从指向
Base
的智能指针更改为指向
Derived
的智能指针

提前谢谢


更新:我的第二个示例确实没有编译,多亏了Iammilind我想到了一些想法。首先,如果可以执行第一个版本,只需将该
克隆
保留为隐藏,然后编写另一个受保护的
\u克隆
,实际返回派生指针。
Clone
都可以使用它

这就引出了一个问题,你为什么要这样做。另一种方式可以是强制(外部)功能,在该功能中,您可以接收
共享\u ptr
,如果可能,还可以将其强制为
共享\u ptr
。也许是这样的:

template <typename B, typename D>
shared_ptr<D> coerce(shared_ptr<B>& sb) throw (cannot_coerce)
{
// ...
}
模板
共享\u ptr强制(共享\u ptr&sb)抛出(无法强制)
{
// ...
}

您不能直接执行,但有几种方法可以借助非虚拟接口习惯用法来模拟它

对原始指针使用协方差,然后包装它们
struct Base
{
私人:
虚拟基*doClone()常量{…}
公众:
shared_ptr Clone()常量{返回shared_ptr(doClone());}
虚拟~Base(){}
};
派生结构:基
{
私人:
虚拟派生*doClone()常量{…}
公众:
shared_ptr Clone()常量{返回shared_ptr(doClone());}
};
这仅在实际有原始指针开始时有效

通过铸造模拟协方差
struct Base
{
私人:
虚拟共享\u ptr doClone()常量{…}
公众:
共享的_ptr Clone()常量{return doClone();}
虚拟~Base(){}
};
派生结构:基
{
私人:
虚拟共享\u ptr doClone()常量{…}
公众:
共享\u ptr Clone()常量
{return static_pointer_cast(doClone());}
};
在这里,您必须确保
Derived::doClone
的所有重写实际上返回指向
Derived
或从其派生的类的指针

在本例中,
Derived::Clone
隐藏
Base::Clone
,而不是覆盖它

,它不会隐藏它。事实上,这是一个好主意

不能使用仅在返回类型上不同的另一个函数重写或隐藏虚拟函数;因此,返回类型应该相同,否则程序是非法的,因此会出现错误


因此,这意味着没有其他方法可以将
shared_ptr
转换为
shared_ptr
。唯一的方法是建立
B*
D*
关系(你在问题中已经排除了这一点)。

使用@ymett技术可以改进一个伟大的游戏。这样,您就不必担心忘记在派生函数中添加非虚函数

struct Base
{
private:
   virtual Base* doClone() const { ... }

public:
   shared_ptr<Base> Clone() const { return shared_ptr<Base>(doClone()); }

   virtual ~Base(){}
};

template<class T>
struct CRTP_Base : Base
{
public:
   shared_ptr<T> Clone() const { return shared_ptr<T>(doClone()); }
};

struct Derived : public CRTP_Base<Derived>
{
private:
   virtual Derived* doClone() const { ... }
};
struct Base
{
私人:
虚拟基*doClone()常量{…}
公众:
shared_ptr Clone()常量{返回shared_ptr(doClone());}
虚拟~Base(){}
};
模板
结构CRTP_基础:基础
{
公众:
shared_ptr Clone()常量{返回shared_ptr(doClone());}
};
派生结构:公共CRTP_基
{
私人:
虚拟派生*doClone()常量{…}
};

@Kerrek可能是因为
Clone()
也可能在非多态上下文中调用,在非多态上下文中不希望丢失类型信息。正确的名称是协变返回类型,可能会提高一点。可能的重复为什么C++委员会解决问题,然后再引入另一个麻烦?非常感谢。这很有意义+1这是我推荐的解决方案。(实际上,我一开始就建议不要使用
共享ptr
。函数返回
共享ptr
很少是好策略。但同样的解决方案也适用于
自动ptr
或其他智能指针。)我在这里支持@James Kanze:在界面中使用特定的共享指针会迫使用户选择智能指针。考虑使用不同的味道或智能指针(<代码> UnQuyPPTR <代码>,<代码> AutoPPTR <代码>?)或原始指针,以打开对用户的选择。(
unique_ptr
auto_ptr
的优点是,用户可以获得该指针的所有权并将其传递给不同的智能指针类型,而
shared_ptr
用户不能放弃所有权)@James Kanze同意,如果要创建对象,请使用unique_ptr和第一个解决方案。如果已经有了SyrdYPTR(例如,对象是从商店检索的,可能是弱的PTR的——不太可能给出函数名),那么使用第二个解决方案。这仍然是C++需要解决的最大问题之一。在任何地方使用shared_ptr都是非常有用的,但是这样做仍然是一个很大的麻烦。是的,你是对的。这是个错误。很抱歉,问题不正确:)返回类型必须相同的语句错误。C++允许协变指针/引用返回类型(协变意味着当你在一个继承层次中向下移动时,重写的返回类型必须是相同的,或者是在它自己继承层次上的对象),你是指一些东西。
struct Base
{
private:
   virtual shared_ptr<Base> doClone() const { ... }

public:
   shared_ptr<Base> Clone() const { return doClone(); }

   virtual ~Base(){}
};

struct Derived : Base
{
private:
   virtual shared_ptr<Base> doClone() const { ... }

public:
   shared_ptr<Derived> Clone() const
      { return static_pointer_cast<Derived>(doClone()); }
};
struct Base
{
private:
   virtual Base* doClone() const { ... }

public:
   shared_ptr<Base> Clone() const { return shared_ptr<Base>(doClone()); }

   virtual ~Base(){}
};

template<class T>
struct CRTP_Base : Base
{
public:
   shared_ptr<T> Clone() const { return shared_ptr<T>(doClone()); }
};

struct Derived : public CRTP_Base<Derived>
{
private:
   virtual Derived* doClone() const { ... }
};