פורסם 2010 בספטמבר 2215 שנים אני כרגע מתחזק שני קלאסים נפרדים (שאינם יורשים זה מזה) ובכל קלאס אני מבצע פעולות גם על אוביקט מהסוג השני.כלומר כל קלאס עושה אינקלוד לשני.נוצרת לי פה בעיה של forwarding, ואני קצת מתקשה להתמודד איתה.האינקלודים שלי ממוקמים בקבצי הידר, ובכל אחד מהם וגם בקבצי סי.פי.פי (לא רוצה שהטקסט יתבלגן, לכן בעברית..) הוספתי גם את ההצהרה class X, כאשר מדובר בקלאס השני.לאחר ביצוע הפעולה הנ"ל, הכל עובד כשורה. יש לי בנאי שמקבל מהסוג השני, ועובד, ובצורה דומה גם בקלאס האחר שלי.בקלאס א' יצרתי אופרטור שמקבל כפרמטר אוביקט מקלאס ב', וזה עובד מעולה.כעת אני רוצה לבצע את אותו האופרטור בקלאס ב'.לצורך העניין האופרטור הוא +=.בקלאס ב', היכן שאני כעת מעוניין לבצע זאת, הפעולה נכשלת ואני מקבל בתגובה את ההערה הבאה:in member function "......:operator+=(...):error:invalid use of incomplete type 'const struct A'error: forward declaration of 'const struct A'כך חוזר על עצמו עוד פעמיים, בכל מקום בו ביצעתי קריאה לאיזו מתודה של הצד השני.אזכיר שנית כי בשני ההידרים קיים אינקלוד להידר האחר, וגם ההצהרה "קלאס ....".
פורסם 2010 בספטמבר 2215 שנים forward declaration עובד רק כשאתה מעביר מצביעים, ולא את הקלאס עצמו. כלומר, כזה דבר יעבוד:class A;class B { void f(A* obj);}בעוד שכזה דבר לא יעבוד:class A;class B { void f(A obj);}הסיבה היא שבמקרה הראשון, הקומפיילר לא צריך לדעת איך בדיוק נראית המחלקה A (כי הוא רק מעביר מצביע), ובמקרה השני הוא כן צריך לדעת.אגב, יש סיכוי שזה דווקא כן יעבוד:class A;class B { void f(A& obj);}שווה לך לבדוק. בכלל, בד"כ כשמעבירים אובייקטים לפונקציה מומלץ להעביר אותו באמצעות &, כדי למנוע שכפול מיותר.נ.ב. להבא, תעלה דוגמת קוד. לא תמיד ברור מהניסוח מה בדיוק עשית, ובקלות יכול להיות שהשגיאה נובעת מטעות תחבירית אחרת.
פורסם 2010 בספטמבר 2215 שנים מחבר אני מעביר רפרנס (כדי למנוע שכפול מיותר)כלומר אני נמצא באופציה 3 שהצעת.ככה ביצעתי גם את הפונקציה המקבילה בקלאס האחר שלי, ושם זה עובד.לצורך המחשה יותר עמוקה, המבנה הוא כזה:/// B.h#include ...#include ...#include "A.h"class A;class B {private:...public:....B& operator+=(const A& other){......return *this;}...};/// A.h#include ...#include ...#include "B.h"class B;class A {private:...public:....A& operator+=(const B& other){......return *this;}...};בהידר של 'איי' זה עובד היטב, כפי שכבר ציינתי, אך בהידר של 'בי', אני מקבל הערה על הforward decleration of const struct Aובמתודה עצמה של האופרטור חיבור שציינתי, אני מקבל 3 הערות על כל מקום בו ביצעתי קריאה דרך האובייקט פרמטר למתודה של הקלאס האחר - מתודות GET פשוטות ולא נסיון לכתיבה עליהם.
פורסם 2010 בספטמבר 2215 שנים כמו שאמרתי, לא בטוח שעניין הרפרנס יעבוד - תנסה להשתמש במצביע כדי לראות אם זה פותר את הבעיה (כן, אני יודע שזה משנה את החתימה של האופרטור, אבל זה רק בשביל לנסות בינתיים).
פורסם 2010 בספטמבר 2215 שנים מחבר שיניתי מרפרנס לפוינטר, את כל הגישות שיניתי מ- . ל- ->, ועדיין אותו הדבר.
פורסם 2010 בספטמבר 2215 שנים אז תעלה את הקוד המלא (או לפחות את החלקים הרלוונטיים) ואת הודעת השגיאה המדוייקת. כולל מספרי שורות.ועוד הערה קטנה - עדיף להימנע מאינקלודים מיותרים. אם כזה עשית forward declaration, אז אתה כנראה לא צריך את ה-include בכלל.
פורסם 2010 בספטמבר 2215 שנים מחבר החלקים החשובים בהידר הבעייתי:#ifndef SPARSEMATRIX_H_#define SPARSEMATRIX_H_#include <cstdlib>#include <vector>#include <cassert>#include "SparsePoint.h"#include "Number.h"#include "RegMatrix.h"using namespace std;class RegMatrix;class SparseMatrix {private: vector<SparsePoint> _matrix;void MergeClones(); int _numRow, _numCol;public: int GetColumns() const; int GetRows() const; const vector<SparsePoint>& GetMatrix() const; SparseMatrix(int numRow, int numCol); SparseMatrix(int numRow, int numCol, double fill[]); SparseMatrix(const SparseMatrix &other); SparseMatrix(const RegMatrix &other); virtual ~SparseMatrix();........SparseMatrix& operator+=(const RegMatrix& other) { assert((_numCol == other.GetColumns()) && (_numRow == other.GetRows())); int pos = 0; for (int i = 0; i < _numRow; ++i) for (int j = 0; j < _numCol; ++j) { SparsePoint p(i,j,(other.GetMatrix()).at(pos)); _matrix.push_back(p); ++pos; } MergeClones(); return *this; }......};#endifרוב המתודות דיי ברורות מטבען, וניתן להבין מההגיון, P הוא בעצם אובייקט שמחזיק מיקום ואוביקט מסוג מספר, שהוא פשוט מספר עם עוד כמה תכונות אחרות שאני צריך.כל שאר המתודות במחלקה הזו פועלות.השגיאה המתקבלת היא:../SparseMatrix.h: In member function ‘SparseMatrix& SparseMatrix::operator+=(const RegMatrix&)’:../SparseMatrix.h:47: error: invalid use of incomplete type ‘const struct RegMatrix’../SparseMatrix.h:11: error: forward declaration of ‘const struct RegMatrix’../SparseMatrix.h:47: error: invalid use of incomplete type ‘const struct RegMatrix’../SparseMatrix.h:11: error: forward declaration of ‘const struct RegMatrix’../SparseMatrix.h:52: error: invalid use of incomplete type ‘const struct RegMatrix’../SparseMatrix.h:11: error: forward declaration of ‘const struct RegMatrix’כאשר שורה 47: ה assertשורה 11: ההצהרה class RegMatrixשורה 52: האיתחול של P.
פורסם 2010 בספטמבר 2215 שנים א. מה עם ההגדרה של RegMatrix?ב. המימוש של הפונקציה נמצא בתוך הקובץ h?ג. כמו שאמרתי קודם - לא עושים גם include וגם forward declaration, זה חסר טעם.
פורסם 2010 בספטמבר 2215 שנים מחבר סליח לי :-[ללא ספק, הבעיה פה נודדת לה מקצה לקצה.כעת הסרתי אינקלוד לספרס בהידר של רגולר, מאחר ועשיתי שם את ההצהרה על class SparseMatrixאז כעת הקומפיילר מעיר לי על בעיות ב RegMatrix, עבור קונסטרקטור שמקבל Sparse.ההערה תואמת לקודמתה.חסכתי את הגזירה-הדבקה של כל מיני דברים ארעיים, וכדי למנוע עוד יותר בלבול העברתי לך בפרטי לינק לקבצים הספציפיים, לעיון נוח וקריא יותר..כעת ראיתי את התגובה הנוספת:א - טופלב - כןג - טופל ולכן העדכון שבתחילת ההודעה
פורסם 2010 בספטמבר 2215 שנים אומר שוב: איפה שאתה עושה forward declaration, אל תעשה אינקלוד.חוץ מזה, למה יש לך מימושים של פונקציות בקובץ h? תממש רק בקובץ cpp (אלא אם אתה כותב פונקציות inline או template, ואז זה קצת יותר מורכב).
פורסם 2010 בספטמבר 2215 שנים מחבר את העניין עם ה forward declaration כבר סידרתי, כלומר כעת הוא לא מופיע יחד עם אינקלודלגבי איפה מימשתי מה, גם לי מעט תמוה, אבל ככה אני ועוד כמה מסביבי שמענו את המרצה אומר במהלך השיעור - שאת האופרטורים כדאי לממש בהידר.יותר הגיוני שהכוונה הייתה רק לאלו שמוגדרים כ friend, לכן אני אתקן את זה כעת.[br]פורסם בתאריך: 22.09.2010 בשעה 16:01:35אוקיי, תיקנתי את מרבית אי-הסדר שהיה,אך עדיין נותרתי עם אותה בעיה כמקודם..:../RegMatrix.cpp: In constructor ‘RegMatrix::RegMatrix(const SparseMatrix&)’:../RegMatrix.cpp:46: error: invalid use of incomplete type ‘const struct SparseMatrix’../RegMatrix.h:9: error: forward declaration of ‘const struct SparseMatrix’../RegMatrix.cpp:46: error: invalid use of incomplete type ‘const struct SparseMatrix’../RegMatrix.h:9: error: forward declaration of ‘const struct SparseMatrix’../RegMatrix.cpp:49: error: invalid use of incomplete type ‘const struct SparseMatrix’../RegMatrix.h:9: error: forward declaration of ‘const struct SparseMatrix’../RegMatrix.cpp:49: error: invalid use of incomplete type ‘const struct SparseMatrix’../RegMatrix.h:9: error: forward declaration of ‘const struct SparseMatrix’../RegMatrix.cpp: In member function ‘RegMatrix& RegMatrix::operator+=(const SparseMatrix&)’:../RegMatrix.cpp:156: error: invalid use of incomplete type ‘const struct SparseMatrix’../RegMatrix.h:9: error: forward declaration of ‘const struct SparseMatrix’../RegMatrix.cpp:156: error: invalid use of incomplete type ‘const struct SparseMatrix’../RegMatrix.h:9: error: forward declaration of ‘const struct SparseMatrix’../RegMatrix.cpp:159: error: invalid use of incomplete type ‘const struct SparseMatrix’../RegMatrix.h:9: error: forward declaration of ‘const struct SparseMatrix’../RegMatrix.cpp:159: error: invalid use of incomplete type ‘const struct SparseMatrix’../RegMatrix.h:9: error: forward declaration of ‘const struct SparseMatrix’
פורסם 2010 בספטמבר 2215 שנים ב-RegMatrix.h הורדת את include SparseMatrix שזה טוב, אבל היית צריך לשים את האינקלוד הזה ב-RegMatrix.cpp במקומו.
פורסם 2010 בספטמבר 2215 שנים מחבר לא אוכל לתאר עד כמה אני מודה לך. טכנית, הבנתי - ההצהרה על הקלאס בהידר, והאינקלוד ב .cpp, אבל לא מבחינה תיאורטית. אני מגשש ברשת כדי לקבל הסבר רחב יותר, אבל בכל הקשור ל C\C++, מלבד cplusplus.com /cppreference לא מצאתי יותר מדי, וגם אלו יותר דומים ל API מאשר סוג של tutorial, כמו שקיים בג'אווה למשל.
פורסם 2010 בספטמבר 2215 שנים כשאתה עושה INCLUDE לקובץ H, אתה בעצם מביא את כל המחלקות שמוגדרות בו, את כל המתודות שמוגדרות בו ובפרט את כל המשתנים שמוגדרים במחלקה.ברגע שהורדת את הinclude לקובץ הH, הקומפיילר, למעשה, לא מודע לכל הDATATYPES שמוגדרים במחלקה, ולכן הוא לא יודע כמה הוא צריך להקצות לך על המחסנית כשאתה שולח את האובייקט לפונקציה. אם אתה שולח מצביע, אז הוא מודע לגודל של המצביע (4 בתים בדרך כלל, תלוי במחשב שלך), ןלכן אין בעיה להעביר אותו.
פורסם 2010 בספטמבר 2215 שנים מחבר את כל מה שאמרת אני מבין, אבל לא התייחסת לעניין ההצהרה "class X"האם כלל האצבע הוא כזה - בעת שיש לי שני הידרים שהאחד תלוי בשני וההפך, מצב שביצוע אינקלוד יצור סתירה כלשהיא, אז אני בעצם רק מצהיר על class X, וזה מחליף לי את האינקלוד, כלומר נותן לי גישה לשיטות וכד'?מה שלא מסתדר לי עד הסוף הוא שאם אני מבצע בקובץ CPP אינקלוד ל H שלו, שהוא כבר הצהיר על class X, מדוע זה "לא תופס" ?
ארכיון
דיון זה הועבר לארכיון ולא ניתן להוסיף בו תגובות חדשות.