AKToRloN Δημοσ. 17 Αυγούστου 2005 Δημοσ. 17 Αυγούστου 2005 Τo προβλημα ειναι με τα include στα διαφορα αρχεια. Δηλωνω την κλαση Date στο Date.h με class Date{ (μεθοδοι,μεταβλητες) } Στο Date.cpp κανω τα εξης : #include "Date.h" Date:: Date(){...} ... και μετα στη main ενα προγραμμα που χρησιμοποιει την κλαση Date με #include "Date.h" ... και μου πεταει unresolved ολες τις συναρτησες που εχω υλοποιησει στο .cpp. Aν κανω include και το Date.cpp στη main ολα καλα (κατι που δεν γινεται οταν χρησιμοποιω συνθεση και εκει ειναι κυριως το προβλημα). Aπο οτι εχω δει σε ενα βιβλιο (Deitel) γραφει οτι το include τον υλοποιησεων των κλασσεων ειναι "κακη πρακτικη" και θελω να δω πως γινεται στον υπολοιπο κοσμο. p.s Απο οτι ξερω(ή νομιζω τουλαχιστον ) δεν κανω κυκλικη συμπεριληψη.
kickeras Δημοσ. 17 Αυγούστου 2005 Δημοσ. 17 Αυγούστου 2005 to include einai fovera xrisimo gia to linking. Min ksexnas panw panw sto .h na vazeis #pragma once an exeis .net i ta gnwsta #endif. Sou petaei unresolved giati: example function sto .h: int& get_day(); sto .cpp: int& Date::get_day() {......;} to function sto .h prepei na einai opws sto example an thes na to exeis kai sto .cpp. An thes na to exeis mono sto .h logw p.x. oti einai mikro function tote einai opws exeis Date:: Date(){...} twra afta ta kikliki simperilipsi kai tetoia den exw idea ti simainoun kathws den kserw ellinious orous.
godlike Δημοσ. 17 Αυγούστου 2005 Δημοσ. 17 Αυγούστου 2005 Αυτό ήταν ένα θέμα με πονοκεφαλιάσει πριν πολύ καιρό. Σε ένα .h βάζεις τις κλάσεις. Aν έχεις δηλώσεις μεταβλητών ή δηλώσεις συναρτήσεων τις κάνεις extern. Να ένα παράδειγμα: FileGenerator.h >#ifndef _FILEGENERATOR_H_INCLUDED_ #define _FILEGENERATOR_H_INCLUDED_ #include "Main.h" class FILEGENERATOR { public: char* chv_outputFileName; int CreateOBJFile (void); }; extern FILEGENERATOR fileGen; //Εδώ λεω ότι έχω ένα αντικείμενο τύπου FILEGENERATOR και ότι είναι extern. //Με αυτήν την δήλωση ο Linker θα παει να ψάξει αλλού για την δήλωση #endif FileGenerator.cpp > #include "FileGenerator.h" FILEGENERATOR fileGen; int FILEGENERATOR::CreateOBJFile (void) { RaiseMessage("\nCreating file %s ...\n", this->chv_outputFileName); HANDLE hndl = CreateFile(this->chv_outputFileName, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, 0, 0); if ((int)hndl == -1 || GetLastError()==ERROR_ALREADY_EXISTS) { RaiseMessage("-->ERROR: Can't create %s file. File is probably open\n", this->chv_outputFileName); return 0; } int x = (int)(rawSegPointer) - (int)(&rawSegment); WriteFile(hndl, &rawSegment, x, (DWORD*)&x, NULL); RaiseMessage("OK, '%s' created. Size %i bytes\n", this->chv_outputFileName, GetFileSize(hndl, NULL)); CloseHandle(hndl); return 1; } Αν θες π.χ. στην main σου αν χρησιμοποιήσεις την κλάση FILEGENERATOR τότε κάνεις μόνο #include “FileGenerator.h” και λες στο project σου να κάνει compile και link με το FileGenerator.cpp. Π.χ. στην VC++ 6 πας 'Project'->'Add To Project'->'Add Files' και επιλέγεις το FileGenerator.cpp
AKToRloN Δημοσ. 18 Αυγούστου 2005 Μέλος Δημοσ. 18 Αυγούστου 2005 THANX godlike οντως αυτο ηταν. Ομως μου φαινεται λιγο περιεργο ο τροπος με τον οποιο δουλευει ,δηλαδη δηλωνω ενα αντικειμενο το οποιο δεν θα το χρειαστω ποτε ως extern, το οποιο το οριζω στο .h ,μονο και μονο για να δει το αρχειο στο οποιο γινεται η υλοποιηση. Και για να βρει τις υλοποιησεις του .h ,θα συνδεσει τα 2 αρχεια λογω του extern και θα βρει και και την υλοποιηση τους στο cpp. Ψιλοπεριεργο ειναι να σου πω την αληθεια αλλα αφου δουλευει ολα okz. Οσο για το #pragma δεν το χρειαζομαι γιατι δεν εχω ασχοληθει με .NET και γραφω στο VC++ 6. Ομως το ειχα παντα απορια πως συντασεται το #line και πως χρησιμοποιουνται το #pragma και το typedef γιατι το εχω δει να χρησιμοποιηται με ψιλο-"παραδοξους" τροπους που δουλευουν παραυτα. Σε οσα βιβλια και e-books εχω δει, πουθενα δεν λεει ακριβως πως χρησιμοποιουνται. p.s kickeras κυκλικη συμπεριληψη ειναι να κανεις #include το ιδιο αρχειο πανω απο 1 φορες.
godlike Δημοσ. 18 Αυγούστου 2005 Δημοσ. 18 Αυγούστου 2005 Είναι λίγο περίεργο αλλά θα σου πω ακριβώς γιατί. Συνήθως στα .cpp γράφεις τα bodies των συναρτήσεων και ορίζεις και global μεταβλητές ή αντικείμενα. A.cpp >#include “A.h” int x = 0; int func (void) { return 1; } Στο αντίστοιχο .h βάζεις τις δηλώσεις των κλάσεων, τις δηλώσεις των structs και αν θες να βλέπουνε όλοι κάποια συνάρτηση ή κάποια global var τις ορίζεις με το extern μπροστά. Α.h >extern int x; extern int func (void); Αν δεν έχεις σκοπό στο πάνω .h να μοιράσεις το x για παράδειγμα δεν χρειάζεται να το βάλεις στο .h σαν extern. Καλό είναι όμως να ορίζεις τα πάντα σαν extern στο .h γιατί πρώτων έχεις την πλήρη εποπτεία για το τι υπάρχει στο .cpp και δεύτερον για να βλέπουν οι ίδιες οι συναρτήσεις του ίδιου του .cpp τα πάντα. A.cpp > int func (void) { return func2(); //ERROR } int func2 (void) { return 1; } Εδώ π.χ. θέλω να μοιράσω μόνο την func. Άμα ορίσω μόνο την func σαν extern στο .h τότε ο compiler θα βγάλει error (στην γραμμή του ERROR) και θα σου πει ότι δεν έχεις ορίσει την func2. Λογικό γιατί δεν ξέρει ακόμα για την func2. Άμα όμως κάνεις τα πάντα extern τότε δεν θα έχεις πρόβλημα. Με αυτόν τον τρόπο βλέπουνε οι πάντες τους πάντες αλλά κοστίζει σε compilation time
Προτεινόμενες αναρτήσεις
Αρχειοθετημένο
Αυτό το θέμα έχει αρχειοθετηθεί και είναι κλειστό για περαιτέρω απαντήσεις.