2011-09-25 5 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 référence par rapport à la valeur est un trait du type plutôt que du paramètre de la fonction. Venant de C++, cela me fait vraiment mal.Comment transmettre un objet par valeur?

Il semble qu'il y ait un mot-clé ref pour forcer le renvoi par référence pour les fonctions acceptant struct s. Existe-t-il un tel équivalent pour le passage de class es en valeur? Par exemple, disons que je veux créer une fonction qui renvoie une copie triée d'une classe de conteneur personnalisée. Par exemple, En C++, c'est aussi simple que d'utiliser Foo Sorted(Foo Object), par opposition à Foo Sort(Foo& Object). Je ne vois aucun moyen de le faire en D sans copier manuellement l'objet.

+1

même avec des objets de classes, c'est toujours valeur par passe, parce que c'est la référence que vous passez, par valeur – newacct

+3

@newacct Je pense que tout le monde sait ce que l'on entend par "valeur de transmission". – Maxpm

Répondre

11

Les classes sont des types de référence par conception. Ils ne sont pas supposés être passés en valeur. C'est exactement la même chose avec Java et C#. Cependant, contrairement à Java et C#, D a aussi des types de valeurs définis par l'utilisateur à part entière, car il a des structures (C# a aussi des structures, mais elles sont beaucoup plus limitées). Le fait que C++ confond les deux provoque des problèmes tels que object slicing. Maintenant, évidemment sont fois lorsque vous voulez copier un type de référence. La solution à cela est cloning. Vous donnez à votre classe une fonction clone qui renvoie une copie de l'objet sur lequel il est appelé. De cette façon, vous pouvez le copier quand vous en avez besoin, et il n'est copié que lorsque vous en avez besoin. Java et C# ont une fonction clone standard que la plupart des types implémentent, mais pour une raison quelconque, D ne le fait pas. Je ne suis pas sûr pourquoi. Mais c'est toujours assez facile de déclarer une telle fonction pour vous-même. Il ne va pas être sur Object, ce qui vous permettrait de l'utiliser sur presque n'importe quel objet de classe sans se soucier de ce que le type réel était comme vous pouvez le faire en Java et C#. Vous pouvez toujours créer un constructeur de copie à la place, si vous préférez, mais il est moins flexible, car vous devez connaître le type de l'objet copié, alors qu'avec clone, il peut être de n'importe quel type dérivé du type clone. être Object dans le cas de Java et C# mais serait ce que vous décidiez dans D, puisque la fonction est non-standard).

+1

IIRC certaines choses dans D (tableaux) ont une propriété 'dup'. – BCS

+0

Oui, mais les classes n'implémentent généralement pas une telle fonction. Il se pourrait cependant que l'implémentation d'une fonction appelée 'dup' plutôt que' clone' devienne typique (il n'y a pas encore beaucoup de classes dans la bibliothèque standard, donc je ne pense pas qu'une fonction clone particulière ait été utilisée tous standard encore). Peu importe, c'est le même concept de toute façon. –

+0

Ah. Oui. Je devrais être plus clair: parce que d'autres choses utilisent 'dup', cela peut être une bonne idée de ne pas appeler la fonction' clone'. Garder le même nom peut rendre le code du modèle plus propre. – BCS

4

Oui, utilisez simplement une structure au lieu d'une classe. Mais si vous voulez copier un objet , vous devez implémenter le clonage vous-même. Notez que les concepteurs de D ne l'ont pas inventé; c'est exactement la même chose en C#, et assez similaire en Java. L'objectif est d'empêcher la copie excessive des objets, ce qui est considéré comme un inconvénient de C++ (car il est très caché dans le code).

+0

Voir modification. [15char] – Maxpm

+1

@Maxpm: Voir la 1ère phrase de mon 2ème paragraphe. – Mehrdad

3

Même en C++ ceci:

Foo Sorted(Foo Object) 

est pas utile. Que faire si l'objet est déjà trié et que vous n'avez pas besoin de créer une copie?

En D, vous devrez fournir clone() de certains pour votre classe et l'appeler si nécessaire.

Sinon, utilisez des structures comme Mehrdad mentionné.

Éditer: Ce que "copier l'objet" devrait faire, ce n'est pas clair. S'il a un tableau d'objets à l'intérieur, doit-il cloner ce tableau? Et qu'en est-il des références d'objets qu'il contient? Il est en effet bon que monsieur Walter Bright, auteur de D, n'ait pas fourni de copie des instances de classe par défaut.

Questions connexes