2011-09-25 109 views
7
import std.stdio; 

class IntegerContainer 
{ 
    public int Integer = 1; 
} 

void DoubleInteger(IntegerContainer Container) 
{ 
    Container.Integer *= 2; 
} 

void main() 
{ 
    IntegerContainer Container = new IntegerContainer; // Internal integer defaults to one. 
    DoubleInteger(Container); // Internal integer changes to two inside the function. 
    writefln(Container.Integer); // Prints "2." 
} 

在D中,reference与value是类型的特征,而不是函数参数。来自C++,这对我来说真的很不好。如何通过值传递对象?

看起来好像有一个ref关键字强制通过引用接受struct s的功能。按价值传递class是否有这样的等价物?

例如,假设我想创建一个返回自定义容器类的已排序副本的函数函数。在C++中,这与使用Foo Sorted(Foo Object)一样简单,而不是Foo Sort(Foo& Object)。如果没有手动复制对象,我看不出在D中这样做的方法。

+1

即使是类的对象,它仍然是按值传递的,因为它是您传递的参考,按值 – newacct

+3

@newacct我认为每个人都知道“传递值”的含义。 – Maxpm

回答

11

类是按设计引用的类型。他们不应该被价值传递。这与Java和C#完全相同。然而,与Java和C#不同,D具有完整的用户定义值类型,因为它具有结构(C#也有结构,但它们更受的限制)。 C++混淆了这两个原因导致的问题,如object slicing

现在,显然有次,当你想复制一个引用类型。解决方案是cloning。你给你的班级一个clone函数,它返回被调用的对象的一个​​副本。这样,您可以在需要时将其复制,并且只在需要时复制。 Java和C#拥有大多数类型实现的标准clone函数,但无论出于何种原因,D都没有。我不知道为什么。但是为自己的类型自己声明这样一个函数还是很容易的。它只是不会在Object,这将允许您在几乎任何类对象上使用它,而不关心实际类型是什么样子,你可以在Java和C#中做。如果你愿意,你总是可以创建一个拷贝构造函数,但它不够灵活,因为你必须知道被拷贝的对象的类型,而使用clone,它可以是从clone返回的类型派生的任何类型在Java和C#的情况下为Object,但由于该函数是非标准的,因此可以是您在D中决定的任何内容)。

+1

IIRC D(数组)中的一些东西具有'dup'属性。 – BCS

+0

是的,但类通常不会实现这样的功能。尽管如此,尽管实现一个名为'dup'而不是'clone'的函数会变得很典型(标准库中没有很多类,所以我不认为特定的克隆函数已经在所有的标准呢)。无论如何,这两种方式都是相同的概念。 –

+0

啊。是。我应该更清楚一点:因为其他东西使用'dup',所以不要调用函数'clone'是个好主意。保持名称相同可能会使模板代码更清晰。 – BCS

4

是的,只需使用结构而不是类。

但是,如果你想复制一个对象,那么你必须自己实施克隆。请注意,D设计师没有做到这一点;它与C#完全相同,在Java中非常相似。目标是防止对象被过度复制,这被视为C++的一个缺点(因为它非常隐藏在代码中)。

+0

请参阅编辑。 [15char] – Maxpm

+1

@Maxpm:请参阅第2段的第1句。 – Mehrdad

3

即使在C++这样的:

Foo Sorted(Foo Object) 

是没有多大用处。如果对象已经排序并且不需要创建副本,该怎么办?

在D中,您需要为您的课程提供clone()这样的一些内容,并在需要时调用它。

否则使用Mehrdad提到的结构。

编辑:目前还不清楚究竟是什么“复制对象”应该做的。如果它内部有对象数组,它将克隆该数组?那它包含的对象引用呢?实际上,D的作者Walter Bright先生没有提供默认情况下复制类实例的好处。