2011-09-25 15 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." 
} 

En D, la referencia en función del valor es un rasgo del tipo, más que del parámetro de la función. Viniendo de C++, esto se siente realmente mal para mí.¿Cómo paso un objeto por valor?

Parece que hay una palabra clave ref para forzar el paso por referencia para las funciones que aceptan struct s. ¿Hay un equivalente para pasar class es por valor?

Por ejemplo, supongamos que quiero hacer una función que devuelva una copia ordenada de una clase de contenedor personalizada. En C++, es tan simple como usar Foo Sorted(Foo Object), a diferencia de Foo Sort(Foo& Object). No veo forma de hacer esto en D sin copiar manualmente el objeto.

+1

incluso con objetos de clases, todavía está pasado de moda, porque es la referencia que está pasando, por valor – newacct

+3

@newacct Creo que todos saben lo que significa "pasar por valor". – Maxpm

Respuesta

11

Las clases son tipos de referencia por diseño. Se supone que no deben pasar por valor. Es exactamente lo mismo con Java y C#. Sin embargo, a diferencia de Java y C#, D también tiene tipos de valor definidos por el usuario completos, ya que tiene estructuras (C# también tiene estructuras, pero son más más limitadas). El hecho de que C++ combine los dos causa problemas como object slicing.

Ahora, obviamente, son veces cuando desea copiar un tipo de referencia. La solución a eso es cloning. Le das a tu clase una función clone que devuelve una copia del objeto al que se llama. De esta forma, puedes copiarlo cuando lo necesites, y solo se copiará cuando lo necesites. Java y C# tienen una función estándar clone que la mayoría de los tipos implementan, pero por alguna razón D no lo hace. No estoy seguro por qué. Pero aún es bastante fácil declarar esa función para sus propios tipos. Simplemente no va a estar en Object, lo que le permitiría usarlo en casi cualquier objeto de clase sin preocuparse de cómo era el tipo real, como lo puede hacer en Java y C#. Siempre puede crear un constructor de copia, si lo prefiere, pero es menos flexible, porque debe conocer el tipo de objeto que se está copiando, mientras que con clone, puede ser cualquier tipo derivado del tipo que devuelve clone (que ser Object en el caso de Java y C# pero sería lo que decida en D, ya que la función no es estándar).

+1

IIRC algunas cosas en D (matrices) tienen una propiedad 'dup'. – BCS

+0

Sí, pero las clases generalmente no implementan tal función. Podría ser que se convierta en típico implementar una función llamada 'dup' en lugar de' clone' aunque (no hay muchas clases en la biblioteca estándar todavía, así que no creo que una función de clonación en particular haya estado en todo estándar aún). De todos modos, es el mismo concepto de cualquier manera. –

+0

Ah. sí. Debería ser más claro: porque otras cosas usan 'dup', puede ser una buena idea no llamar a la función' clone'. Mantener el mismo nombre puede hacer que el código de la plantilla sea más limpio. – BCS

4

Sí, solo use una estructura en lugar de una clase.

Pero si desea copiar un objeto , debe implementar la clonación usted mismo. Tenga en cuenta que los diseñadores de D no inventaron esto; es exactamente de la misma manera en C#, y bastante similar en Java. El objetivo es evitar que los objetos se copien en exceso, lo que se ve como una desventaja de C++ (ya que está muy escondido en el código).

+0

Ver la edición. [15char] – Maxpm

+1

@Maxpm: Ver la 1ra oración de mi 2 ° párrafo. – Mehrdad

3

Incluso en C++ esto:

Foo Sorted(Foo Object) 

no es tan útil. ¿Qué ocurre si el Objeto ya está ordenado y no necesita crear una copia?

En D tendrá que proporcionar clone() de algunos tales para su clase y llámelo si es necesario.

De lo contrario, use las estructuras como Mehrdad mencionó.

Editar: No está claro exactamente qué debería hacer "copiar el objeto". Si tiene una matriz de objetos dentro, ¿debe clonar esa matriz? ¿Y las referencias a objetos que contiene? De hecho, es bueno que monsieur Walter Bright, autor de D, no haya proporcionado copias de las instancias de clase por defecto.

Cuestiones relacionadas