MitsakosGR Δημοσ. 13 Ιουλίου 2010 Δημοσ. 13 Ιουλίου 2010 Καλημέρα σε όλους, προσπαθώ να φτιάξω ένα πρόγραμμα το οποίο να χρησιμοποιεί static μεταβλητές σε classes. Το πρόβλημα που αντιμετωπίζω είναι το εξής: Όταν η class και η αρχικοποίηση των static μεταβλητών είναι μέσα στο .h αρχείο, τότε δεν μπορώ να κάνω πολλαπλά include το συγκεκριμένο .h αρχείο γιατί μου βγάζει ότι έχω ορίσει πολλές φορές την ίδια μεταβλητή. Αν βγάλω την αρχικοποίηση των static μεταβλητών από το .h και την βάλω σε κάποιο σημείο που καλείται μόνο μία φορά (πχ σε ένα .cpp αρχείο) τότε δεν έχω κανένα πρόβλημα και όλα παίζουν κανονικότατα. Παραθέτω εδώ τον κώδικα που έχω γράψει: Αρχείο errorClass.h >#ifndef ERRORCLASS_H #define ERRORCLASS_H class Error{ static int errorNum; public: static int getError(){ return errorNum; } }; int Error::errorNum = 1; #endif /* ERRORCLASS_H */ Αρχείο main.cpp >#include "errorClass.h" int main(){ } Αρχείο second.cpp >#include "errorClass.h" Αν βγάλω το int Error::errorNum = 1; από το errorClass.h και το βάλω στο second.cpp δεν υπάρχει κανένα πρόβλημα, αλλά θα το προτιμούσα να μείνει στο errorClass.h ... Αφού υπάρχει το #ifndef ERRORCLASS_H δεν υποτίθεται ότι θα τα τρέξει μόνο μία φορά και όχι κάθε φορά που κάνεις include το αρχείο αυτό;; Τα μηνύματα λάθους από το VS είναι: Error 1 error LNK2005: "private: static int Error::errorNum" (?errorNum@Error@@0HA) already defined in main.objError 2 error LNK1169: one or more multiply defined symbols found και από το NetBeans με Cygwin_4 και G++ -4 build/Debug/Cygwin_4.x-Windows/second.o:second.cpp:(.data+0x0): multiple definition of `Error::errorNum'build/Debug/Cygwin_4.x-Windows/main.o:main.cpp:(.data+0x0): first defined here
Evgenios1 Δημοσ. 13 Ιουλίου 2010 Δημοσ. 13 Ιουλίου 2010 Καλημέρα σε όλους,προσπαθώ να φτιάξω ένα πρόγραμμα το οποίο να χρησιμοποιεί static μεταβλητές σε classes. Το πρόβλημα που αντιμετωπίζω είναι το εξής: Όταν η class και η αρχικοποίηση των static μεταβλητών είναι μέσα στο .h αρχείο, τότε δεν μπορώ να κάνω πολλαπλά include το συγκεκριμένο .h αρχείο γιατί μου βγάζει ότι έχω ορίσει πολλές φορές την ίδια μεταβλητή. Αν βγάλω την αρχικοποίηση των static μεταβλητών από το .h και την βάλω σε κάποιο σημείο που καλείται μόνο μία φορά (πχ σε ένα .cpp αρχείο) τότε δεν έχω κανένα πρόβλημα και όλα παίζουν κανονικότατα. Παραθέτω εδώ τον κώδικα που έχω γράψει: Αρχείο errorClass.h >#ifndef ERRORCLASS_H #define ERRORCLASS_H class Error{ static int errorNum; public: static int getError(){ return errorNum; } }; int Error::errorNum = 1; #endif /* ERRORCLASS_H */ Αρχείο main.cpp >#include "errorClass.h" int main(){ } Αρχείο second.cpp >#include "errorClass.h" Αν βγάλω το int Error::errorNum = 1; από το errorClass.h και το βάλω στο second.cpp δεν υπάρχει κανένα πρόβλημα, αλλά θα το προτιμούσα να μείνει στο errorClass.h ... Αφού υπάρχει το #ifndef ERRORCLASS_H δεν υποτίθεται ότι θα τα τρέξει μόνο μία φορά και όχι κάθε φορά που κάνεις include το αρχείο αυτό;; Τα μηνύματα λάθους από το VS είναι: και από το NetBeans με Cygwin_4 και G++ -4 Εμμ.. Βαλε και ενα #define ERRORCLASS_H μετα το include (second.cpp) υγ: Στην ms μπορεις να βαλεις #pragma once αντι του file guard
V.I.Smirnov Δημοσ. 13 Ιουλίου 2010 Δημοσ. 13 Ιουλίου 2010 Mάλλον δεν έχεις καταλάβει τι είναι δήλωση και τι ορισμός μεταβλητής. Το >int Error::errorNum = 1; ΔΕΝ είναι δήλωση (declaration) αλλά ορισμός (definition) και ΔΕΝ πρέπει να βρίσκεται σε include αρχείο. Η σωστή πρακτική είναι να αρχικοποιηθεί σε ένα από τα cpp που περιέχουν το h. Γι αυτό χτυπάει ο compiler. Αυτό που έγραψε ο Evgenios Εμμ.. Βαλε και ενα #define ERRORCLASS_H μετα το include (second.cpp) είναι λάθος. Για να δουλέψει στο VS πρέπει να το βάλεις ΠΡΙΝ από ένα από τα #include "errorClass.h" ή στο ίδιο το errorClass.h ΠΡΙΝ από το #ifndef ERRORCLASS_H . Δηλ. ανάποδα από το προφανές. Mπορείς να πας και στo μενού project-->properties-->...preprocessor definitions και να θέσεις εκεί το όνομα ERRORCLASS_H οπότε το #define ERRORCLASS_H δεν χρειάζεται καν. Πέρα από αυτό, όλα τα παραπάνω είναι φορμαλιστικώς λαθεμένα και δεν είναι σίγουρο ότι θα δουλέψουν εκτός του VS. Σε include αρχεία πρέπει να τίθενται μόνον δηλώσεις κι' όχι ορισμοί. -
MitsakosGR Δημοσ. 13 Ιουλίου 2010 Μέλος Δημοσ. 13 Ιουλίου 2010 Στην αρχή που διάβαζα το μήνυμα διάβαζα Declared, όχι Defined, για αυτό έγραψα για δήλωση και όχι ορισμό, συγνώμη για αυτό. Πέρα από αυτό, όλα τα παραπάνω είναι φορμαλιστικώς λαθεμένα και δεν είναι σίγουρο ότι θα δουλέψουν εκτός του VS.Σε include αρχεία πρέπει να τίθενται μόνον δηλώσεις κι' όχι ορισμοί.- Δεν θα χρησιμοποιήσω το #pragma once αν σε αυτό αναφέρεσαι γιατί δεν το αναπτύσσω σε VS αλλά σε NetBeans, απλά έχω συνηθίσει τα μηνύματα λάθους του VS και όταν δεν καταλαβαίνω κάτι από το g++ το βάζω στο VS να δω τι είναι. Αυτό που μου έκανε εντύπωση είναι ότι πάει να κάνει compile και build το συγκεκριμένο κομμάτι κώδικα ενώ πίστευα ότι δεν έπρεπε. Δηλαδή αφού είναι μέσα στο #ifndef και έχει γίνει ήδη defined ο compiler θα το αγνοήσει εντελώς. Τελικά το έβαλα σε άλλο .cpp αρχείο και ξεμπέρδεψα με αυτό. Ευχαριστώ για τις απαντήσεις σας.
V.I.Smirnov Δημοσ. 13 Ιουλίου 2010 Δημοσ. 13 Ιουλίου 2010 Δεν θα χρησιμοποιήσω το #pragma once αν σε αυτό αναφέρεσαι... Δεν αναφέρομαι στο #pragma once. Το #pragma once αφορά μόνον το VS. Τα #ifndef, #define, #endif είναι standard. Παραταύτα, το τέχνασμα να τεθεί το #define πριν από το #ifndef, δηλ. ανάποδα από το προφανές, δεν είναι είναι βέβαιο ότι θα δουλέψει εκτός του VS. Aυτό εννοώ. Αυτό που μου έκανε εντύπωση είναι ότι πάει να κάνει compile και build το συγκεκριμένο κομμάτι κώδικα ενώ πίστευα ότι δεν έπρεπε. Δηλαδή αφού είναι μέσα στο #ifndef και έχει γίνει ήδη defined ο compiler θα το αγνοήσει εντελώς. Τελικά το έβαλα σε άλλο .cpp αρχείο και ξεμπέρδεψα με αυτό. Στο ξαναλέω, άλλο πράγμα είναι η δήλωση και άλλο ο ορισμός μεταβλητής. Tα include αρχεία δεν πρέπει να περιέχουν ορισμούς. Το ότι μέσα στο include έθεσες ορισμό κι' όχι δήλωση είναι λάθος και μπερδεύει τον compiler και γι' αυτό δεν λειτουργεί σωστά το #ifndef.
NewProject Δημοσ. 13 Ιουλίου 2010 Δημοσ. 13 Ιουλίου 2010 γιατι γραφεις : > [font=monospace]int Error::errorNum = 1; [/font] αντι για : > Error::errorNum = 1; ;
V.I.Smirnov Δημοσ. 13 Ιουλίου 2010 Δημοσ. 13 Ιουλίου 2010 @ΝewProject Τι γιατί ; Aφού το Error::errorNum δεν έχει οριστεί. Τo int Error::errorNum = 1; είναι ΟΡΙΣΜΟΣ. Συνεπώς το int απαιτείται !
NewProject Δημοσ. 14 Ιουλίου 2010 Δημοσ. 14 Ιουλίου 2010 αλλα το εχει κανει ηδη μια φορα στο : > class Error { [font=monospace] static int errorNum;[/font] };
MitsakosGR Δημοσ. 14 Ιουλίου 2010 Μέλος Δημοσ. 14 Ιουλίου 2010 αλλα το εχει κανει ηδη μια φορα στο : > class Error { [font=monospace] static int errorNum;[/font] }; Η πρώτη φορά που δίνεις τιμή (αρχικοποίηση, σωστά V.I.Smirnov;; ) σε static variable πρέπει να γίνει στο Global scope και να έχει αυτή τη μορφή: dataType Class::Variable = value; Παράθεση από το cplusplus.com tutoria για static variables σε classes (Static members) Static members have the same properties as global variables but they enjoy class scope. For that reason, and to avoid them to be declared several times, we can only include the prototype (its declaration) in the class declaration but not its definition (its initialization). In order to initialize a static data-member we must include a formal definition outside the class, in the global scope
Προτεινόμενες αναρτήσεις
Αρχειοθετημένο
Αυτό το θέμα έχει αρχειοθετηθεί και είναι κλειστό για περαιτέρω απαντήσεις.