בעיה של linkage...

אורגד

New member
בעיה של linkage...

אולי אתם תוכלו לעזור לי. כתבתי כאן תוכנית פשוטה, והשתמשתי בה במבנה נתונים קיים של QuadTree (עם עוד כמה דברים שהוא מבוסס עליהם). מבנה-הנתונים הזה נמצא בתוך namespace-ים. משום מה, התוכנית לא מסכימה לעבור link. אני משתמש ב-Microsoft Visual C++ 6.0. שימו לב שיש שם קובץ בשם Region2D.cpp, ויש בו את הפונקציות שלגביהן הקומפיילר טוען שהן לא קיימות. זאת ההודעה שאני מקבל:
Compiling... main.cpp QuadMesh.cpp QuadTree.cpp Region2D.cpp Tree.cpp Linking... main.obj : error LNK2001: unresolved external symbol "public: virtual __thiscall Rage::NTree::Region2D<char>::~Region2D<char>(void)" (??1?$Region2D@D@NTree@Rage@@UAE@XZ) main.obj : error LNK2001: unresolved external symbol "public: void __thiscall Rage::NTree::Region2D<char>::initialize(int,int,char *)" (?initialize@?$Region2D@D@NTree@Rage@@QAEXHHPAD@Z) main.obj : error LNK2001: unresolved external symbol "public: __thiscall Rage::NTree::Region2D<char>::Region2D<char>(void)" (??0?$Region2D@D@NTree@Rage@@QAE@XZ) Debug/Rage.exe : fatal error LNK1120: 3 unresolved externals Error executing link.exe. Rage.exe - 4 error(s), 0 warning(s)​
 

HaRmosh

New member
אז ככה...

לדעתי, תוסיף קובץ h. שמכיל את הצהרות הפונקציות בלבד, ותכליל אותו בעזרת include בקובץ המדובר, שמשתמש בפונקציות ה"נעלמות". אם זה לא עוזר, כנראה שלא הוספת את הקובץ cpp לפרוייקט, אבל אם כן... כאן נגמרות לי העצות. בהצלחה
 

orgads

New member
כבר יש כזה קובץ!

וה-cpp כן בפרוייקט! זה בדיוק מה שאני לא מבין! גררררר...
 

ברנדל

New member
גבר

כשאתה עובד עם templates, שים את ההגדרות בקובץ של ה header קובץ ה header צריך להראות כך:
#ifndef REGION2D_H #define REGION2D_H static char ident_str_Region2D[] = "$Header: /users/reid/rageroot/repository/r1/src/NTree/Region2D.h,v 1.5 2002/05/20 17:57:40 pkf Exp $"; namespace Rage { namespace NTree { template<class T> class Region2D { public: Region2D(); virtual ~Region2D(); void initialize( int nrows, int ncols, T* data ); void createData(); size_t getNumCols() { return numCols_m; } size_t getNumRows() { return numRows_m; } size_t getNumData() { return numRows_m * numCols_m; } T* getData1D() { return data_1d_m; } T** getData() { return data_m; } protected: size_t numRows_m; size_t numCols_m; T** data_m; T* data_1d_m; }; template<class T> Region2D<T>::Region2D<T>() : numRows_m(0), numCols_m(0), data_1d_m(NULL), data_m(NULL) { } template<class T> Region2D<T>::~Region2D<T>() { if (data_1d_m != NULL) delete data_1d_m; if (data_m != NULL) delete [] data_m; } // // Initialize a Region2D with information gotten from a Mesh or Tree // getRegion() call. Calculate the corresponding 2D data array. // template<class T> void Region2D<T>::initialize(int nrows, int ncols, T* data) { numRows_m = nrows; numCols_m = ncols; data_1d_m = data; createData(); } // // Create the 2D array from the 1D array by creating the pointers into // the actual data which remains in 1D form // template<class T> void Region2D<T>::createData() { if (data_1d_m == NULL) { std::cout << "Null pointer passed into createData" << std::endl; } if ((numRows_m <= 0) || (numCols_m <= 0)) { std::cout << "Size parameters must be positive integers" << std::endl; } data_m = new T*[numRows_m]; for (int r = 0; r < numRows_m; r++) { data_m[r] = data_1d_m + (r * numCols_m); } } } // namespace NTree } // namespace Rage #endif /* #ifndef REGION2D_H */​
את הקובץ השני ( cpp ) אתה יכול להוריד עם המים בשרותים
 

ברנדל

New member
גבר

יש לך גם bug קטן ה destructor שלך צריך להיות ככה:
template<class T> Region2D<T>::~Region2D<T>() { if (data_1d_m == NULL) delete data_1d_m; if (data_m != NULL) delete [] data_m; }​
תשנה את זה
 

ברנדל

New member
גבר

התכוונתי:
Region2D<T>::~Region2D<T>() { if (data_m != NULL) delete []data_m; }​
data_1d_m לא מוקצה בשום הקצאה דינמית, אז אסור לעשות לו delete
 
למעלה