Προς το περιεχόμενο

C++ Static Variables


MitsakosGR

Προτεινόμενες αναρτήσεις

Δημοσ.

Καλημέρα σε όλους,

προσπαθώ να φτιάξω ένα πρόγραμμα το οποίο να χρησιμοποιεί 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.obj

Error 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

Δημοσ.
Καλημέρα σε όλους,

προσπαθώ να φτιάξω ένα πρόγραμμα το οποίο να χρησιμοποιεί 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

Δημοσ.

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 αρχεία πρέπει να τίθενται μόνον δηλώσεις κι' όχι ορισμοί.

 

-

Δημοσ.

Στην αρχή που διάβαζα το μήνυμα διάβαζα Declared, όχι Defined, για αυτό έγραψα για δήλωση και όχι ορισμό, συγνώμη για αυτό.

 

Πέρα από αυτό, όλα τα παραπάνω είναι φορμαλιστικώς λαθεμένα και δεν είναι σίγουρο ότι θα δουλέψουν εκτός του VS.

Σε include αρχεία πρέπει να τίθενται μόνον δηλώσεις κι' όχι ορισμοί.-

 

Δεν θα χρησιμοποιήσω το #pragma once αν σε αυτό αναφέρεσαι γιατί δεν το αναπτύσσω σε VS αλλά σε NetBeans, απλά έχω συνηθίσει τα μηνύματα λάθους του VS και όταν δεν καταλαβαίνω κάτι από το g++ το βάζω στο VS να δω τι είναι.

Αυτό που μου έκανε εντύπωση είναι ότι πάει να κάνει compile και build το συγκεκριμένο κομμάτι κώδικα ενώ πίστευα ότι δεν έπρεπε. Δηλαδή αφού είναι μέσα στο #ifndef και έχει γίνει ήδη defined ο compiler θα το αγνοήσει εντελώς.

 

Τελικά το έβαλα σε άλλο .cpp αρχείο και ξεμπέρδεψα με αυτό.

Ευχαριστώ για τις απαντήσεις σας.

Δημοσ.

Δεν θα χρησιμοποιήσω το #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.

Δημοσ.
αλλα το εχει κανει ηδη μια φορα στο :

>
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

Αρχειοθετημένο

Αυτό το θέμα έχει αρχειοθετηθεί και είναι κλειστό για περαιτέρω απαντήσεις.

  • Δημιουργία νέου...