2010-02-04 7 views
1

Si c'est le cas, qu'est-ce que c'est censé faire?Est-ce que le code C++ valide est le suivant?

typedef struct Foo_struct{ 
    Dog d; 
    Cat* c; 
    struct Foo_struct(Dog dog, Cat* cat){ this->d = dog; this->c = cat;} 
} Foo; 

(histoire de retour: le portage d'un programme écrit en Visual C++ (sous Windows) à g ++ (sur MacOSX), aucune idée de ce que ce code est suppoesd à faire).

Merci!

Répondre

8

Je ne pense pas que ce soit. (Et Comeau est d'accord avec moi.) Vous ne pouvez pas définir un constructeur comme celui-ci.

En C++, les noms de structure sont des citoyens de première classe. Il n'est pas nécessaire d'utiliser l'ancienne astuce typedef de C. En outre, d et c doivent être initialisés dans une liste d'initialisation de membre. Ce serait valable (et mieux (C++):

struct Foo { 
    Dog d; 
    Cat* c; 
    Foo(Dog dog, Cat* cat) : d(dog), c(cat) {} 
}; 

Le code définit un struct (en C++, même en tant que classe, sauf que ses membres sont publiques par défaut) avec un constructeur pour initialiser ses membres sur création

Edit:. comme Travis a dit dans son commentaire, vous voudrez peut-être envisager de passer dog comme référence const au lieu de le copier:

Foo(const Dog& dog, Cat* cat) : d(dog), c(cat) {} 

Si Dog (que nous n'avons pas vu) est une classe avec plus d'un membre intégré, cela pourrait être considérablement moins cher que de le passer par copie.

+3

Ou mieux encore 'Foo (const chien et chien, chat * chat): d (chien), c (chat) {}' ... évite le surdébit d'instancier 'd' juste pour l'écraser avec un paramètre. Et passer par référence est moins cher et plus C++. –

+0

@Travis: Je modifiais le code pour le faire pendant que vous ajoutiez votre commentaire. ':)' – sbi

+0

@Travis - Pas de bébé. :) –

0

On dirait qu'il définit une structure appelée Foo_Struct, qui contient une instance de Dog, a un pointeur sur un chat, et a un constructeur qui prend une instance de Dog, pointeur vers Cat, et les assigne à lui-même.

Ensuite crée une instance de Foo sur la pile. Edit: Je ne suis pas sûr si cette troisième ligne est un constructeur ou quelque chose d'autre.

3

C'est presque légal mais il y a une erreur. Une structure est juste comme une classe sauf que la protection par défaut est publique et non privée.

D'accord, nous allons le décomposer:

// The next line is defining a struct called "Foo_struct", it's also 
// saying it's going to give an alternate type name (that's the typedef). 
// The alternate type name comes after the definition. 
typedef struct Foo_struct{ 

    // The structure has a Dog element (this means we need to have seen 
    // the definition of Dog already). 
    Dog d; 

    // And has a pointer to cat (this means we need to have at least seen 
    // a declaration of Cat) 
    Cat* c; 

    // Okay, this is definining a constructor. The constructor must be 
    // called with a Dog object and a pointer to a cat which the constructor 
    // will save in the object. 
    // 
    // Here is the one error. That 'struct' at the start shouldn't 
    // be there (commenting out to make the code legal). 
    /* struct */ Foo_struct(Dog dog, Cat* cat){ this->d = dog; this->c = cat;} 

// And here we close out the struct and also finish off the typedef 
// started on the first line. 
} Foo; 
+0

@Samual: Je changerais le texte en lisant "... est en train de créer une structure appelée ..." à "... est en train de créer une structure _type_ appelée ...". Au moins autour de l'endroit où je vis (les anglophones non-natifs) "créer une structure" serait compris comme créant un _objet_ du type de la structure, pas comme créant un type struct. Cela pourrait être juste nous non-indigènes ici, cependant. +1 de toute façon, puisque vous avez raison autrement. – sbi

+0

@sbi - merci pour les commentaires; Je l'ai changé pour "définit une structure appelée". –

5

Non, ce n'est pas le cas. Vous ne pouvez pas avoir le struct dans le constructeur. Un code C++ valide avec un changement minimal serait

typedef struct Foo_struct{ 
    Dog d; 
    Cat* c; 
    Foo_struct(Dog dog, Cat* cat){ this->d = dog; this->c = cat;} // <-- remove the "struct" 
} Foo; 

Pour une meilleure approche voir @ réponse de l'OSMŒ.

4

Principalement, bien que les struct et typedef ne soient pas nécessaires. Mieux écrit en C++ comme:

class Foo { 
    public: 
    Foo(Dog dog, Cat *cat) : d(dog), c(cat) {} 
    private: 
    Dog d; 
    Cat *c; 
}; 

ligne par ligne:

class Foo { 

La même chose que struct Foo.La seule différence en C++ entre un class et un struct est que les membres de struct sont publics par défaut, tandis que les membres de class sont privés. Mais nous avons besoin de certains membres du public quelque part, donc nous vous débrouillez avec ...

public: 

Tout après est public et peut être consulté par toute personne ayant un objet Foo.

Foo(Dog dog, Cat *cat) : d(dog), c(cat) {} 

Ceci est le constructeur de Foo. Il fait un nouvel objet Foo, donné un Dog et un Cat *. Le : d(dog), c(cat) est une liste d'initialisation. C'est le même que this->d = dog; this->c = cat;, sauf probablement plus rapide. Si vous ne voulez pas le faire de cette façon, vous pouvez laisser le this-> à moins qu'il y ait un conflit de nommage quelque part. Le {} est le corps de la fonction, vide car nous avons déplacé l'affectation vers la liste d'initialisation.

private: 

En face de public:. Les choses déclarées après cela ne sont accessibles que dans notre classe, et sont uniquement destinées à un usage interne.

Dog d; 
    Cat *c; 

Ce sont des variables internes, comme les membres d'une struct de la classe.

+0

'class' n'est pas exactement la même chose que' struct' puisque 'class' est par défaut une visibilité privée. – kennytm

Questions connexes