הגדרת operator>> לostream.

selalerer

New member
הגדרת operator>> לostream.

יצרתי מחלקת string קטנה שלי בכדי לבדוק את המימוש של אופרטורים. עשיתי אופרטור >> בכדי לעשות פלט לסטרינג אל cout הגדרתי אותו כfriend ומימשתי אותו מחוץ למחלקה, אך למרות שהוא הוגדר כfriend הקומפיילר (VC) נותן לי טעות שאין לו גישה אל המשתנה הפנימי (המצביע אל המחרוזת) כשאני ממש אותו בתוך המחלקה אז הוא כן מקבל את זה, זה לא כלכך מובן לי למה, אם הוא friend אז הוא אמור להיות מסוגל לגשת אל המשתני private של המחלקה שלי (עשיתי את זה עם פונקציה רגילה וזה עבד מצויין). מצורף הקובץ לשם הבהרה מה לא עובד, מה שכן עובד זה שאיפה שיש את ההכרזה על האופרטור כfriend אז לשים גם שם את המימוש. השאלה למי שלא הבין: למה הוא לא נותן לי לגשת למשתנה private מתוך operator שהוא friend? תודה, סלע.
 

annefan

New member
חביב

VS באמת מבלבל. ++G נתן לי את הכיוון:
/usr/include/c++/3.3.1/bits/ios_base.h: In copy constructor ` std::basic_ios<char, std::char_traits<char> >::basic_ios(const std::basic_ios<char, std::char_traits<char> >&)': /usr/include/c++/3.3.1/bits/ios_base.h:668: error: ` std::ios_base::ios_base(const std::ios_base&)' is private sela.cpp:39: error: within this context sela.cpp: In function `int main(int, char**)': sela.cpp:39: error: initializing argument 1 of `void operator<<(std::basic_ostream<char, std::char_traits<char> >, str)'​
קאפיש? הבעיה היא האופרטור שלך, שמקבל אוביקט ostream, ולא refernce לאוביקט. האופרטור מנסה להפעיל copy-constructor של ostream, שמה לעשות, הוא private, ולכן הקומפילציה נכשלת. (בשביל דקויות שכאלה יש לי גם GCC על המחשב. ההודעות של VS דפוקות, שזה כואב.) (אגב, לא צריך להגיד לך שלמימוש מלא, האופרטור צריך לקבל reference ל-str, ולהחזיר reference ל-ostream, נכון?)
 

annefan

New member
הקומפיילר של GNU

gcc - Gnu's Compiler Collection​
ה-front-end ל-++C נקרא ++g.
 

selalerer

New member
זה מבלבל,אז עכשיו תגיד לי למה זה...

...כן עובד:
#include <iostream> using namespace std; class str { private: char *str1; public: str(const char *pstr) { str1=new char[strlen(pstr)+1]; strcpy(str1,pstr); } str(str &s1) { str1=new char[strlen(s1.str1)+1]; strcpy(str1,s1.str1); } ~str() { delete []str1; } friend void operator<<(ostream os,const str s1) { os << s1.str1; } }; int main(int argc,char *argv[]) { str s1("Hello World!"); cout << s1; return 0; }​
אבל גם מה שאמרת לא עובד, גם אם אני מקבל את הostream כbyreference אז הוא עדין נותן לי שגיאה ש"str1" זה פרטי והוא לא יכול לגשת אליו. *בקשר להערה שלך, רק אחרי שאמרת את זה חשבתי על מה שאמרת, שצריך לעשות את זה בכדי שיוכלו לעשות עוד >> אחריו. אתה לוקח את זה כמובן מאליו אבל לי לקח זמן לקלוט את זה. תודה, סלע.
 

selalerer

New member
הנה עוד משהו שכן עובד, וזה אפילו די

יפה:
using namespace std; class str { private: char *str1; public: str(const char *pstr) { str1=new char[strlen(pstr)+1]; strcpy(str1,pstr); } str(str &s1) { str1=new char[strlen(s1.str1)+1]; strcpy(str1,s1.str1); } ~str() { delete []str1; } //friend ostream &operator<<(ostream &os,str &s1); operator const char*() { return (const char *)str1; } }; ostream &operator<<(ostream &os,str &s1) { os << (const char *)s1; return os; } int main(int argc,char *argv[]) { str s1("Hello World!"); cout << s1 << " And some more." << endl; return 0; }​
אבל הייתי רוצה להבין למה הקודם לא עובד? תודה רבה, סלע.
 

selalerer

New member
עכשיו אני ממש מבולבל, אותו קוד שלא

עבד בVS כן עובד בGCC (בdev c++) עכשיו אני ממש בדיכאון על MS, חולירות!
 

annefan

New member
זה עובד!

#include <iostream> using namespace std; class str { private: char *str1; public: str(const char *pstr) { str1=new char[strlen(pstr)+1]; strcpy(str1,pstr); } str(str &s1) { str1=new char[strlen(s1.str1)+1]; strcpy(str1,s1.str1); } ~str() { delete []str1; } friend void operator<<(ostream &os,const str &s1); }; void operator<<(ostream & os,const str &s1) { os << s1.str1; } int main(int argc,char *argv[]) { str s1("Hello World!"); cout << s1; return 0; } (זו כמובן, הגירסה הראשונה שלך, מלבד הוספת &.​
 

selalerer

New member
כן אני יודע, כבר ניסיתי את זה על...

...++dev c אבל לטעמי הגרסה עם ההמרה ל*const char היא יותר יפה, זה מעצבן שהקומפיילר לא תואם תקן, ואני צריך לחפש מה יעבוד בכולם. תודה רבה.
 

annefan

New member
לא הבנת

הקוד הזה מתקמפל ורץ על VS.NET (2003), ו-GCC. הקטע עם האופרטור מיותר. אתה מפעיל עוד קריאת פונקציה סתם.
 

selalerer

New member
אני יכול לעשות את זה inline.

בקשר לזה שזה מתקמפל, סביר ביותר שהגרסה של הVS שלי היא ישנה, ואז גם הקומפיילר ישן. אני יכול להחליף לגרסה חדשה של הקומפיילר בלי בעיות תאימות? בנושא דומה: עשיתי ניסוי עם string.reserve, נראה שדווקא GCC מתעלם מהבקשה שלי לשמור מקום ברוב המקרים בעוד VC נענה, יש איזה סיבה?
 

annefan

New member
להחליף ל-VS.NET?

אני ממליץ בחום. קומפיילר טוב יותר, סטנדרטי יותר, קפדן יותר. אבל, אני לא עובד באפליקציות של MFC וכד'.
 

Mapisto

New member
תנסה

במקום להצהיר על void אלא על ostream.
ostream& operator<< (ostream& os,str & mystring) ;​
 

selalerer

New member
לא זאת הבעיה, זה לא משנה את השגיאה

זה כאילו הוא מתעלם ממהצהרה על friend.
 
למעלה