עבור לתוכן

C++, עזרה בתכנון מחלקות ומתודות.

Featured Replies

פורסם

שלום לכולם,

אני לא אפרסם קוד כי זה בעיה בתכנון ולא בעיית תחביר, וגם הקוד מפוזר על הרבה קבצים אז סתם יהיה ארוך.

הבעיה:

מחלקת בסיס: class1, מחלקה יורשת: class 2, ו-3 מחלקות נוספות שיורשות מ-class2 והן: classA, classB, classC ויש מחלקה נוספת שיורשת מ-class1 והיא שונה מהאחרות לכן הייתי צריך את class2

שאלת ביניים: מתודות וירטואליות טהורות עדיף לממש במחלקה הבסיסית ביותר או במחלקה המורישה הכי קרובה למחלקה בה אני ממש את המתודה?

במימוש שלי ב-class2 נמצאות 3 מתודות וירטואליות טהורות שממומשות במחלקות היורשת ממנה.

יש לי רשימה מקושרת טמפלטית של class1 כאשר המידע ברשימה הוא מסוג .classA/ classB/classC

classA, classB, classC מקבלות מידע מסוים ואמורות לשרשר את המידע בהתאם לסוגו, וכל אחת מממשת את המתודות הוירטואליות בצורה שונה.

אני מקבל אינדקס מסויים וצריך להכניס את המידע לרשימה המקושרת לפי האינדקס, ללכת לנוד המתאים ולהכניס שם, פה הבעיה:

בשביל לעבור על הרשימה אני צריך ליצור מצביע ל-class1 (כי סוגי הנודים שונים והמשותף ביניהם זה class1) ואז כאשר הגעתי לנוד שאני צריך אני צריך להשתמש במתודה הוירטואלית, אבל ב-class1 אין את הפונקציות הוירטואלית.

מקווה שהבעיה ברורה, אם יש שאלות נוספות אני אנסה להבהיר.

תודה לעוזרים.

פורסם

תשובת ביניים - המתודה הוירטואלית שלך צריכה להיות במחלקה בה לראשונה יש משמעות למתודה הזו. לדוגמא - יש לך מחלקה של חיה ממנה יורשת מחלקת כלב וממחלקת הכלב יורשות מחלקות לברדור ופינצר, אז המתודה הוירטואלית "תנבח" צריכה להיות בכלב, והמימוש צריך להיות ב"לברדור" וב"פינצר".

למה לא כל האיברים מהרשימה הם מסוג class2? אם כל סוגי הNODEים הם מסוג class1, אז גם הפונקציה הוירטואלית צריכה להיות משותפת ביניהם. מכיוון שהפונקציה הוירטואלית מוגדרת רק עלclass2, אז הרשימה כנראה צריכה להיות רק על class2.

מה בידיוק המחלקות מייצגות?

פורסם

unsigned integer צודק. באופן כללי, עדיף להמנע מהכנסת אובייקטים משתי היררכיות שונות לאותה רשימה.

בהנחה שאין ברירה, אתה יכול לעשות downcast דינמי ל-class2 ואם הוא מצליח, לבצע את הפעולה הרצוייה.

אבל זה לא פתרון אידיאלי כי הוא בעצם מתדרדר לרמה של "תוציא אובייקט. אם הוא כלב - תנבח. אם הוא תפוח - תאכל. אם הוא צוללת גרעינית - שגר טילים."

פורסם
  • מחבר

unsigned integer צודק. באופן כללי, עדיף להמנע מהכנסת אובייקטים משתי היררכיות שונות לאותה רשימה.

בהנחה שאין ברירה, אתה יכול לעשות downcast דינמי ל-class2 ואם הוא מצליח, לבצע את הפעולה הרצוייה.

אבל זה לא פתרון אידיאלי כי הוא בעצם מתדרדר לרמה של "תוציא אובייקט. אם הוא כלב - תנבח. אם הוא תפוח - תאכל. אם הוא צוללת גרעינית - שגר טילים."

תתפלא, אבל תרגילי בית באוניברסיטה ופתרונות אידיאלים לא הולכים יד ביד, את כל התרגיל ניתן לפתור בצורה קלילה ללא שימוש בירושה כלל.. אבל צריך ללמוד ירושה...

פורסם
  • מחבר

שאלה נוספת:

יש לי מיון ברשימה מקושרת טמפלטית, ואני לפעמים מקבל אובייקט ולפעמים מצביע לאובייקט, אני מנסה להעמיס אופרטור השוואה לגבי המצביעים, כך שישוו את המידע הרלוונטי מהתא אליהם הם מצביעים:


{
if (class1->get_id() < class2->get_id())
return true;
else
return false;
}
bool operator<(X* const& class1, X* const& class2)

האם ניתן לעשות דבר כזה?!

שאלה נוספת: האם ניתן לעשות template specialization רק למתודה אחת במחלקה? אם כן איך התחביר? האם אני צריך להצהיר שוב במחלקה על המתודה?

תודה רבה מראש

פורסם

כל עוד אתה לא ממיר מ- class1 ל- class2, ולא מנסה לגשת למתודות הוירטואליות דרך הרשימה שלך, אין עם זה בעיה.

וכן, אפשר ליצור TEMPLATE SPECIALIZATION עבור מתודה ספציפית.

פורסם
  • מחבר

כל עוד אתה לא ממיר מ- class1 ל- class2, ולא מנסה לגשת למתודות הוירטואליות דרך הרשימה שלך, אין עם זה בעיה.

וכן, אפשר ליצור TEMPLATE SPECIALIZATION עבור מתודה ספציפית.

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

לגבי template specialization של מתודה ספציפית במחלקה, האם זה יראה כך?:


template<class T>
class Myclass
{
public:
void foo();
template <> void foo();
}


template<class T>
void Myclass::foo()
{}

template<>
void Myclass<int>::foo
{}

פורסם

אופרטורי השוואה? לא דיברתי עליהם בכלל. מה אתה מנסה לעשות בידיוק?

ובנוגע לקוד שלך - זה אמור להיראות משהו כזה:



#include <iostream>


using namespace std;


template <class T>
class A
{

public:
T data;
A(T d) {data = d;}
T getval() { return data;}
};




A<float>::A(float d) {data = 2.0f * d;}


int A<int>::getval() { return 100;}


int main()


{
A<int> a(3);
A<int *> b(0);
a.data = 4;
b.data = &a.data;

A<float> f(2.6);

cout<<f.getval()<<" "<<a.getval()<<" "<<b.getval();
char str[10];
cin.getline(str, 10);



return 0;
}




פורסם
  • מחבר

אופרטורי השוואה? לא דיברתי עליהם בכלל. מה אתה מנסה לעשות בידיוק?

אני מעוניין להשוות בין שני אובייקטים אבל שאני מקבל מצביעים אליהם, האופרטור אמור לגשת לאובייקט עצמו ולהשוות שדה מסויים, לפי מה שקראתי ברשת הדבר בלתי אפשרי.

למשל:


int* p1 =&num1
int* p2 =&num2

if(p1<p2)
...

אז האופרטור ייגש למספר עצמו וישווה ביניהם, ולא ישווה בין הכתובות.

פורסם

אתה יכול לעשות:




if (*p1 < *p2) {
....
}

פורסם
  • מחבר

אני מדבר על השוואה טמפלטית, אני לא יודע מה סוג המשתנה שאני מקבל, יכול להיות int, יכול להיות מצביע למחלקה מסויימת

פורסם

אם המחלקה הגדירה >operator אז לא תהיה בעיה.

אם לא, איך אתה מצפה להשוות בלי שהמחלקה תאמר איך עושים את זה?

פורסם
  • מחבר

אני ארשום שוב את כל המידע הנחוץ כי לפי התגובות אני רואה שפיספסתם חלק משאלה:

יש לי מחלקה טמפלטית של רשימה מקושרת עם מיון מיזוג מתאים כאחת המתודות.

במיון מיזוג אני משתמש באופרטור ">" הבעיה שפעם אחת אני מקבל int ופעם אחת אני מקבל מצביע לאחת המחלקות שלי, נקרא לה X.

לגבי int אין בעיה, האופרטור ההדיפולטי עושה את העבודה, אני מעוניין ליצור העמסה של של האופרטור ">" כך שמקבל שני פוינטרים למחלקה ספציפית ומשווה בין שדות ספציפיים בתוך המחלקות.

כפי שרשמתי מימשתי את האופרטור בצורה הבאה (ועשיתי friend למחלקה הרלוונטית) :

bool operator<(X* const& class1, X* const& class2)
{
if (class1->get_id() < class2->get_id())
return true;
else
return false;
}

או:

 bool operator<((const X*) & class1, (const X*) & class2)
{
if (class1->get_id() < class2->get_id())
return true;
else
return false;
}

גם זה אחד המימושים שמצאתי ברשת לאחר ניסיונותיי הכושלים להגדיר את האופרטור הנ"ל.

אני מקבל שגיאה שהאופרטור חייב לקבל מחלקה.

עוד שאלה קטנה לגבי קבצים: יש אפשרות ל-VS לזהות כתובת (path) של קובץ במחשב שלי עם שמות תיקיות בעברית?

תודה לכל העוזרים

פורסם

יש כללים מאוד ברורים לאופרטורים. אתה יכול להגדיר אופרטור רק על מחלקות או על referenceים, לא על מצביעים.

פורסם




#include <iostream>


using namespace std;


template <class T>
class Comparer
{
public:
static bool Compare(T v1, T v2);
};


template <class T, class C>
class A
{
public:
T data;
A(T d) {data = d;}
T getval() { return data;}
bool operator<(const A<T, C> & other) const
{
return C::Compare(this->data, other.data);
}
};


bool Comparer<int>::Compare(int v1, int v2)
{
return v1 < v2;
}


bool Comparer<float>::Compare(float v1, float v2)
{
return v1 < v2;
}




bool Comparer<int *>::Compare(int * v1, int * v2)
{
return (*v1) < (*v2);
}


A<float, Comparer<float> >::A(float d) {data = d;}


int A<int, Comparer<int> >::getval() { return 100;}


int main()


{
A<int, Comparer<int> > a(3);
int e = 3;
int h = 10;
A<int *, Comparer<int *> > b(NULL);
A<int *, Comparer<int *> > c(NULL);
A<int *, Comparer<int *> > g(NULL);
a.data = 4;
b.data = &a.data;
c.data = &e;
g.data = &h;

A<float, Comparer<float> > f(2.6);

cout<<f.getval()<<" "<<a.getval()<<" "<<b.getval()<<'\n';
cout<<(b < c)<<"\n"<<(b < g);


char str[10];
cin.getline(str, 10);



return 0;
}






ארכיון

דיון זה הועבר לארכיון ולא ניתן להוסיף בו תגובות חדשות.

דיונים חדשים