פורסם 2010 בספטמבר 1115 שנים היי,אני צריך לשלב בין השניים. הבעיה היא שאני לא מצליח לראות איך אני קורא/כותב איבר מסוג T כלשהו בודד.לדוגמא כאן:template<class T> T CFile<class T>::read() const{}איך אני אומר למשתנה fstream שלי לקרוא T בודד? אם זה INT, STRING או אפילו CLASS שמישהו כתב ועכשיו רוצה להשתמש בREAD שלי...תודה.
פורסם 2010 בספטמבר 1115 שנים לא כל כך הבנתי מה אתה רוצה לעשות. אתה רוצה לממש את הפונקציה read, או שאתה רוצה להשתמש בה?ניסית להשתמש באופרטור >> ?
פורסם 2010 בספטמבר 1115 שנים מחבר לממש..המחלקה נראת ככה:template<class T> class CFile{private: char *_uri; fstream _file; int _begin; int _end;public: CFile(const char *uri) { strcpy(_uri,uri); _file.open(_uri , ios::in | ios::out | ios::app | ios::beg); if(_file.is_open()) { _begin = _file.tellg(); _file.seekg(0,ios::end); _end = _file.tellg(); } } ~CFile() { _file.close(); } /*reads from the file a single T*/ T read() const;};אם אני אעשה << איך ה _file ידע לקרוא את האובייקט שאני אתן לו ולהוציא ממנו את המידע הרלוונטי.ואותו דבר ההפך, איך fstream ידע לטפל ב>> לתוך מחלקה שהוא לא מכיר, כלומר איך הוא ידע כמה לקרוא.לדוגמא אם זה INT אז הוא יודע שהוא צריך לקרוא עד הרווח הבא. ואם זה STRING אז זה עד סוף השורה.או האם אני טועה. האם כל GET מביא את המידע עד הרווח הבא?
פורסם 2010 בספטמבר 1115 שנים הוא יידע אם הגדרת פונקציית <<operator מתאימה לטיפוס הזה. אחרת זה פשוט לא יתקמפל לך. כל מה שאתה צריך לעשות הוא:T x;_file >> x;return x;כמובן, זה מטיל דרישות על T - לטיפוס חייבים להיות מוגדרים בנאי ברירת מחדל, פונקציית <<operator מתאימה (כמו שמגדירים >>operator עבור הדפסה), ו-copy constructor על מנת שתוכל להחזיר אותו מהפונקציה.נ.ב. יש לך באג בבנאי - אתה מעתיק מ-uri ל-uri_, בלי שאתה מאתחל את uri_ להצביע לשום מקום. בכלל, למה לך להשתמש ב-*char ולא פשוט ב-string?
פורסם 2010 בספטמבר 1115 שנים מחבר דרישות מערכת, למרות שנראה לי שלא תיהיה התנגדות אם אני אשנה.בכל אופן אני נתקל בשגיאהError 1 error C2649: 'typename' : is not a 'class' למרות שכמו שאפשר לראות כאן אני כן עושה template<class T> בתחילת הגדרת הפונקציהtemplate<class T> T CFile<class T>::Read() const{ T obj; if(_file.is_open()) { _file >> obj; } if(_file.fail()) { cout << "error while reading file." << endl; return null; } else { return obj; }}
פורסם 2010 בספטמבר 1115 שנים בטמפלייט משתמשים ב-typename ולא ב-classחוץ מזה, איך אתה יכול להחזיר null בתור T? רק מצביע יכול להיות null.
פורסם 2010 בספטמבר 1115 שנים מחבר איזה מוזר בכל המקומות שקראתי על טמפלייט הם כותבים עם CLASS.זה לא כמו C# ? ;Dואיזה עוד אפשרות יש כאשר קראתה שגיאה? אני לא רוצה כל פעם שקורא משהו לזרוק שגיאות..עריכה:ומה עם כתיבה לקובץ.כשאני עושה obj >> _file;המימוש של << לא מתבצע אצל FSTREAM?
פורסם 2010 בספטמבר 1115 שנים אז קראת במקומות מיושנים. ההבדל הוא ש-class לא כולל בתוכו טיפוסים שאינם מחלקות (פרימיטיביים ומצביעים). זה לא כמו ב-#C (שם אפילו לא קוראים לזה templates אלא generics), וזה עובד באופן די שונה.fstream עובד בדיוק כמו cin/cout. בדיוק כמו שאתה מדפיס ל-cout, ככה מדפיסים לקובץ (במקום cout תכתוב file_). כמו שציינתי קודם, זה דורש שיהיה >>operator מוגדר עבור הקלאס שלך.כשמתרחשת שגיאה, הדבר הנכון לעשות הוא לזרוק חריגה (excpetion). מי שקורא לפונקציה read צריך לעטוף אותה ב-try/catch ולטפל בחריגה בהתאם. מבחינת תכנות מונחה עצמים, הקלאס שלך לא צריך להיות אחראי להדפיס הודעת שגיאה - הוא רק צריך לדווח על שגיאה, באמצעות חריגה. מי שתופס את החריגה צריך להחליט אם הוא רוצה להדפיס הודעת שגיאה מתאימה, ואם כן אז לאיפה (למסך, לקובץ וכד').אם אתה בכל זאת רוצה להיות מסוגל להחזיר ערך ברירת מחדל במקרה של שגיאה, הדבר הנכון לעשות הוא ש-read תחזיר *T ולא T. אבל אז תצטרך להקצות אותו דינמית (new), ומי שמשתמש בו יהיה אחראי לשחרר אותו (delete).
פורסם 2010 בספטמבר 1115 שנים מחבר עוד דבר קטןT Read() const throw(CError);הCONST בשורה אומר שאני לא משנה שום אובייקט במחלקה נכון? הוא לא קשור לTHROW או משהו נכון?
פורסם 2010 בספטמבר 1115 שנים אין קשר לחריגה אבל כן יכולה להיות לך בעיה עם הקובץ שאתה קורא כתלות במימוש של המלקה שבפועל קוראת ממנו (ה type של _file במקרה שלך).ברגע שאתה קורא מקובץ אתה משנה את האוביקט שעוטף לך את הקובץ. מכיוון ש CFile שלך מחזיק _file אז למעשה אתה עשוי כבר לא להיות const.בעקרון המהדר אמור לאכוף זאת ע"י כך שאם הגדרת פונ' const על מחלקה מסוימת אז אתה יכול להפעיל רק פונקציות אחרות של המחלקה שהן const. וכן באופן רקורסיבי על אוביקטים אותן המחלקה מכילה. ולכן אם לא מוגדר שגם למשל_file.is_open()הוא const אז אתה בבעיה. (חרא של דוגמה כי is open היא בערך הפונ' היחידה שהיא כן const לפחות ב std::fstream).אם אתה שולט בהגדרות של הפונ' אז אין לך בעיה אבל אם אתה משתמש בספריות כתובות (כגון namespace::std) אז אתה יכול להיות בבעיה.פתרון אפשרי אחד במידה ויש תלונות מצד המהדר הוא להגדיר כאלו משתנים כמו _file כ mutable. אל תשתמש יותר מדי כי אז זה אומר שתה מפספס את הפואנטה של const.
פורסם 2010 בספטמבר 1315 שנים מחבר נשמע הגיוני.עכשיו אני מקבל שגיאה אחרת:Error 1 error LNK2019: unresolved external symbol "public: void __thiscall CFile<class CElement>::Write(class CElement const &)" (?Write@?$CFile@VCElement@@@@QAEXABVCElement@@@Z) referenced in function _main main.objError 2 fatal error LNK1120: 1 unresolved externalsשכאן אין ממש ברירה אלא להוסיף כמעט את כל הקוד:main.cppvoid main(){ try { CElement e1(3); CFile<CElement> file("d:/s.txt"); file.Write(e1); } catch (CError &ex) { cout << ex.getError(); }}cfile.cpp/*write into the file a single T*/template<typename T> void CFile<typename T>::Write(const T& t) throw(CError){ if(apBuf == null) { throw CError("undefined object - null object."); } if(_file.is_open()) { _file << t; if(_file.fail()) { throw CError("error while reading file."); } } else { throw CError("error file not open."); }}cfile.h template<typename T> class CFile{private: string _uri; fstream _file;public: CFile(const string uri) throw(CError) { _uri = uri; _file.open(_uri.c_str() , ios::in | ios::out | ios::app | ios::beg); if(!_file.is_open()) { throw CError("error openning file."); } } ~CFile() { _file.close(); } /*write into the file a single T*/ void Write(const T& t) throw(CError);};celement.hclass CElement{private: int _number;public: CElement(int number) { _number = number; } CElement(const CElement& element) { _number = element._number; } /*set the number to the getting number*/ void Set(const int number); /*return the number*/ int Get() const; friend ostream& operator<<(ostream& out, const CElement& a); friend istream& operator>>(istream& in, CElement& a);};celement.cppostream& operator<<(ostream& out, const CElement& a){ out << a._number; return out;}istream& operator>>(istream& in, CElement& a){ in >> a._number; return in;}אולי הוא לא רואה את הCASTING טוב מהfstream לostream
פורסם 2010 בספטמבר 1315 שנים לא קשור casting, כי אם כן אז הוא היה נותן לך שגיאה בשלב ה-compile, ולא בשלב ה-link.השגיאה אומרת שהוא לא הצליח למצוא את המימוש של Write. נסה להעביר אותו לתוך הקובץ h, כמו הבנאי.(זה קטע כזה שיש עם טמפלייטים, אני אבדוק את הנושא ואחזור אליך)
ארכיון
דיון זה הועבר לארכיון ולא ניתן להוסיף בו תגובות חדשות.