Διαφορά μεταξύ 'struct' και 'typedef struct' στη C++;

Στη C++, υπάρχει κάποια διαφορά μεταξύ:

struct Foo { ... };

και

typedef struct { ... } Foo;
Λύση

Στη C++, υπάρχει μόνο μια λεπτή διαφορά. Είναι ένα κατάλοιπο από τη C, στην οποία έχει διαφορά.

Το πρότυπο της γλώσσας C (C89 §3.1.2.3, C99 §6.2.3, και C11 §6.2.3) επιβάλλει ξεχωριστά namespaces για διαφορετικές κατηγορίες αναγνωριστικών, συμπεριλαμβανομένων των tag identifiers (για struct/union/enum) και των ordinary identifiers (για typedef και άλλα αναγνωριστικά).

Αν απλά είπατε: "Τα αναγνωριστικά είναι τα αναγνωριστικά που χρησιμοποιούνται για την περιγραφή των αναγνωριστικών...":

struct Foo { ... };
Foo x;

θα παίρνατε ένα σφάλμα μεταγλωττιστή, επειδή το Foo ορίζεται μόνο στο χώρο ονομάτων της ετικέτας.

Θα πρέπει να το δηλώσετε ως:

struct Foo x;

Κάθε φορά που θέλετε να αναφερθείτε σε ένα Foo, θα πρέπει πάντα να το ονομάζετε δομή Foo. Αυτό γίνεται γρήγορα ενοχλητικό, οπότε μπορείτε να προσθέσετε ένα typedef:

struct Foo { ... };
typedef struct Foo Foo;

Τώρα το struct Foo (στο χώρο ονομάτων ετικετών) και το απλό Foo (στο συνηθισμένο χώρο ονομάτων αναγνωριστικών) αναφέρονται και οι δύο στο ίδιο πράγμα, και μπορείτε να δηλώσετε ελεύθερα αντικείμενα τύπου Foo χωρίς τη λέξη κλειδί struct.


Η κατασκευή:

typedef struct Foo { ... } Foo;

είναι απλώς μια συντομογραφία για τη δήλωση και το typedef.


Τέλος,

typedef struct { ... } Foo;

δηλώνει μια ανώνυμη δομή και δημιουργεί μια typedef για αυτήν. Έτσι, με αυτή την κατασκευή, δεν έχει όνομα στο χώρο ονομάτων tag, παρά μόνο ένα όνομα στο χώρο ονομάτων typedef. Αυτό σημαίνει ότι δεν μπορεί επίσης να δηλωθεί προς τα εμπρός. Αν θέλετε να κάνετε μια δήλωση προς τα εμπρός, πρέπει να της δώσετε ένα όνομα στο χώρο ονομάτων tag.


Στη C++, όλες οι δηλώσεις struct/union/enum/class συμπεριφέρονται σαν να είναι εμμέσως typedef'ed, εφόσον το όνομα δεν κρύβεται από άλλη δήλωση με το ίδιο όνομα. Δείτε την απάντηση του Michael Burr's για όλες τις λεπτομέρειες.

Σχόλια (16)

Υπάρχει υπάρχει διαφορά, αλλά είναι λεπτή. Δείτε το ως εξής: η δομή Foo εισάγει έναν νέο τύπο. Η δεύτερη δημιουργεί ένα ψευδώνυμο που ονομάζεται Foo (και όχι έναν νέο τύπο) για έναν ανώνυμο τύπο struct.

7.1.3 Ο προσδιοριστής typedef

1 [...]

Ένα όνομα που δηλώνεται με τον προσδιορισμό typedef γίνεται typedef-name. Εντός του πεδίου εφαρμογής της δήλωσής του, ένα typedef-name είναι συντακτικά ισοδύναμο με μια λέξη-κλειδί και ονομάζει τον τύπο που σχετίζεται με το αναγνωριστικό στην με τον τρόπο που περιγράφεται στη ρήτρα 8. Ένα typedef-name είναι επομένως ένα συνώνυμο για έναν άλλο τύπο. Ένα typedef-name δεν εισάγει έναν νέο τύπο όπως κάνει μια δήλωση κλάσης (9.1) ή μια δήλωση enum.

8 Εάν η δήλωση typedef ορίζει μια ανώνυμη κλάση (ή enum), το πρώτο typedef-name που δηλώνεται από τη δήλωση ότι είναι αυτός ο τύπος κλάσης (ή ο τύπος enum) χρησιμοποιείται για να δηλώσει τον τύπο κλάσης (ή τον τύπο enum) για τη σύνδεση σκοπούς μόνο (3.5). [ Παράδειγμα:

typedef struct { } *ps, S; // S is the class name for linkage purposes

Έτσι, ένα typedef πάντα χρησιμοποιείται ως placeholder/συνώνυμο για έναν άλλο τύπο.

Σχόλια (0)

Δεν υπάρχει διαφορά στη C++, αλλά πιστεύω ότι στη C θα σας επέτρεπε να δηλώσετε περιπτώσεις της δομής Foo χωρίς να το κάνετε ρητά:

struct Foo bar;
Σχόλια (1)