- 主题:为啥virtual clone(),返回智能指针,不能covariance?
这个问题的核心实质在于此处返回值是有实际物理内存要求的。如果允许子类重写的函数返回不同类型,那有可能该类型的大小跟父类返回类型大小不同。
基于这个原因,标准里只有指针和引用才有可能covariance
除非将unique_ptr作为语言内置功能,否则以类库的身份是不行的。
【 在 DoorWay 的大作中提到: 】
: virtual unique_ptr<Child> Child::Clone() override;
: 最近有这种需求,子类提供克隆方法,返回自身类型的智能指针,不行。必须返回基类的智能指针?
: 这种一般怎么设计解决?
--
FROM 76.126.252.*
不是吧,java当然是返回子类了。
java里没有值语义,全是指针,天生就covariance了
【 在 hgoldfish 的大作中提到: 】
: 多写一个 dynamic_cast<> 的事,不值得吧。。
: java 的 clone() 同样返回 Object, 而不是子类。
:
--
FROM 76.126.252.*
无法支持,隐形转换不保证大小相同啊。
如果要支持,估计得新加入covariance转换的概念了。
【 在 vonNeumann 的大作中提到: 】
: unique_ptr 毕竟是库实现的,如果要支持,怕是得对所有可以隐式转换的类型都支持才行。。如果单独给 unique_ptr/shared_ptr 开口子那太难看。。
:
--
FROM 76.126.252.*
少敲字不代表优雅。算法意义上的效率才是优雅。
【 在 hgoldfish 的大作中提到: 】
: 我觉得写 c/cpp 时要不辞劳苦,把自己当成人肉编译器。追求效率和精准,而不是去追求代码的优雅。
: 写 python 时则相反,效率不值一分钱,代码优雅实现无误才是王道。
: 两个语言结合起来用,就无敌了。
: ...................
--
FROM 76.126.252.*
如果你一定要这么搞,可以用一虚一实:
class Base {
protected:
virtual Base* CloneData();
public:
unique_ptr<Base> clone() { return {CloneData()}; }
};
class Derived {
protected:
Derived* CloneData() override;
};
【 在 DoorWay 的大作中提到: 】
: 为什么奇葩?是error-prone,还是过于精细?我听不出好坏哈
: 我调研了,希望构造函数可以virtual,是非分之想。
: 这种clone后,希望直接是Child type,调用Child 方法,还算合理的要求吧?
: ...................
--
FROM 76.126.252.*
我猜你应该Java不太熟。
Java里有两个东西:
1. Object基类定义了clone()方法。这个当然是返回Object了。而子类X重写clone()时可以(并且应该)返回X而不是Object。注意这个clone()方法默认是无效的,如果调用它会异常。
2. 有一个接口叫Cloneable.这个接口里其实是没有定义方法的。它的作用是告诉系统定义一个默认的clone()方法(即让1里面原本会抛出异常的行为改变)
【 在 hgoldfish 的大作中提到: 】
: Java 有个 Clonable 接口,里面的 clone() 方法就是返回 Object, 同样要强转。
:
--
FROM 76.126.252.*
此处可以结合底层机理来理解。
函数调用是在栈上面的指针移动,返回值一般就是最后留下来的那一块。如果编译器不知道返回值的大小,那就会有很多问题。
【 在 DoorWay 的大作中提到: 】
: 赞,获得了大略。
: 我的疑问,指针与引用可以,是语言 spec of covariance明确规定,1 convertible 2 sizeof相等了吗?
: 我直觉的以为,只要求convertible 。有没有资料查。
--
FROM 76.126.252.*
我还有一行没写出来。如果你需要子类也返回子类,在子类里也加一个:
unique_ptr<Derived> clone() { return {CloneData()}; }
【 在 hongdiao 的大作中提到: 】
:
: 他这个方案能满足你的要求吗? 返回的类型还是unique_ptr<Base>而不是unique_ptr<Child>啊? 你需求到底是什么?
--
FROM 76.126.252.*
clone本来就不是虚的,CloneData()才是虚的。
所有的目的都达到了呀。
【 在 hongdiao 的大作中提到: 】
:
: 这样的话之类的clone就不是虚函数了啊。 没法通过基类指针或者引用调用。
--
FROM 76.126.252.*