使用智能指针返回类型协方差
Return Type Covariance with Smart Pointers
在c++中我们可以这样做:
struct Base
{
virtual Base* Clone() const { ... }
virtual ~Base(){}
};
struct Derived : Base
{
virtual Derived* Clone() const {...} //overrides Base::Clone
};
但是,下面的代码不会达到同样的效果:
struct Base
{
virtual shared_ptr<Base> Clone() const { ... }
virtual ~Base(){}
};
struct Derived : Base
{
virtual shared_ptr<Derived> Clone() const {...} //hides Base::Clone
};
在这个例子中,Derived::Clone
隐藏了 Base::Clone
而不是重写,因为标准规定重写成员的返回类型只能从引用(或指针)到基到引用(或指针)到派生。有什么聪明的解决方法吗?当然,有人可能会争辩说,Clone
函数应该返回一个普通指针,但现在让我们忘记它-这只是一个说明性的例子。我正在寻找一种方法,可以将虚拟函数的返回类型从智能指针更改为Base
到智能指针Derived
。
提前感谢!
更新:我的第二个例子确实不能编译,由于Iammilind
您不能直接这样做,但是有几种方法可以在非虚拟接口习惯用法的帮助下模拟它。
在原始指针上使用协方差,然后包装它们
struct Base
{
private:
virtual Base* doClone() const { ... }
public:
shared_ptr<Base> Clone() const { return shared_ptr<Base>(doClone()); }
virtual ~Base(){}
};
struct Derived : Base
{
private:
virtual Derived* doClone() const { ... }
public:
shared_ptr<Derived> Clone() const { return shared_ptr<Derived>(doClone()); }
};
这只适用于当你有一个原始指针作为起始点时。
通过转换
模拟协方差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()); }
};
这里你必须确保所有Derived::doClone
的重写确实返回指向Derived
或从它派生的类的指针。
在这个例子中,
Derived::Clone
隐藏了Base::Clone
而不是覆盖它
不,它不会隐藏它。实际上,这是一个编译错误。
不能用另一个只在返回类型上不同的函数覆盖或隐藏虚函数;因此,返回类型应该是相同的或协变的,否则程序是非法的,因此会出现错误。
因此,这意味着没有其他方法可以将shared_ptr<D>
转换为shared_ptr<B>
。唯一的方法是拥有B*
和D*
关系(您已经在问题中排除了)。
@ymett使用CRTP技术对一个很棒的答案进行了改进。这样,您就不必担心忘记在派生类中添加非虚函数。
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 { ... }
};
我想到了一些想法。首先,如果您可以执行第一个版本,只需将Clone
隐藏,和编写另一个实际返回派生指针的受保护_clone
。两个Clone
都可以使用它。
这就引出了你为什么要这样做的问题。另一种方法可能是强制(外部)函数,在该函数中,您可以接收shared_ptr<Base>
,并在可能的情况下将其强制为shared_ptr<Derived>
。也许可以这样写:
template <typename B, typename D>
shared_ptr<D> coerce(shared_ptr<B>& sb) throw (cannot_coerce)
{
// ...
}
- 如何获取std::result_of函数的返回类型
- 奇怪的结构&GCC&clang(void*返回类型)
- 如何建立使用模板函数的lambda函数的尾部返回类型
- 为什么与常规GCC不同,即使有"学究性错误",MinGW-GCC也能容忍丢失的返回类型
- 在没有定义返回类型的函数中返回布尔值,并将结果保存在无错误的char编译中-为什么
- 特征::矩阵<双精度,1,3> 结构类型函数中的返回类型函数
- 函数作为模板参数,是否对返回类型强制约束
- C++中函数的向量返回类型引发错误
- 为什么是谷神星协方差.计算()似乎永远运行而不返回?
- 检查函数返回类型是否与STL容器类型值相同
- 从类型std::函数传递变量失败,尽管调用方期望的类型完全相同
- 为什么返回类型中需要typename?C++
- <Windows>为什么 std::thread::native_handle 返回类型为"long long unsigned int"的值,而不是 void*(又名 HANDLE)?
- 警告:在函数返回类型 [-Wignore 限定符] 时忽略类型限定符
- 为什么 c++(g++) 不允许模板返回类型和函数名称之间有空格?
- 为什么需要返回指针来利用协方差?
- C++协方差返回类型的缺点是什么
- 带有指针返回问题的c++协方差问题
- 接口能否只指定方法名,而不指定返回类型?
- 使用智能指针返回类型协方差