考虑以下代码,其中我希望将一个类(此处为Class2(及其派生类(此处的Class3(的实例存储在另一个类中的数组中(此处为Class1(。如前所述,编译器对最后一行不满意。我做错了什么?
class Class2 {
var y : int;
}
class Class3 : Class2 {
var z : int;
}
class Class1 {
var count : int;
var x : [0..10] owned Class2?;
proc add(ref a : Class2) {
x[count] = a;
count += 1;
}
}
var C1 = new owned Class1();
var C2 = new owned Class2();
var C3 = new owned Class3();
C1.add(C2); // OK
C1.add(C3); // Compiler not happy
编译器输出:
test2.chpl:25: error: unresolved call 'owned Class1.add(owned Class3)'
test2.chpl:14: note: this candidate did not match: Class1.add(ref a: Class2)
test2.chpl:25: note: because call actual argument #1 with type owned Class3
test2.chpl:14: note: is passed to formal 'ref a: owned Class2'
$CHPL_HOME/modules/internal/Atomics.chpl:557: note: candidates are: AtomicT.add(value: T, param order: memoryOrder = memoryOrder.seqCst)
$CHPL_HOME/modules/internal/NetworkAtomics.chpl:280: note: RAtomicT.add(value: T, param order: memoryOrder = memoryOrder.seqCst)
note: and 4 other candidates, use --print-all-candidates to see them
尝试在proc add
:上使用in
意图而不是ref
意图
class Class2 {
var y : int;
}
class Class3 : Class2 {
var z : int;
}
class Class1 {
var count : int;
var x : [0..10] owned Class2?;
proc add(in a : Class2) {
x[count] = a;
count += 1;
}
}
var C1 = new owned Class1();
var C2 = new owned Class2();
var C3 = new owned Class3();
C1.add(C2); // OK
C1.add(C3); // OK!
为什么这很重要?将对子类(Class3(的引用传递给期望引用父类(Class2(的参数是不安全的。特别是,您可以想象该方法将类指针更改为Class2而不是Class3,这可能会导致调用站点出现其他错误。
我的猜测是,add
函数使用ref
的意图只是为了实现C3
的所有权转移。in
意图是一种更好的方法,并且支持传递子类型(因为上面描述的类型错误情况是不可能的(。