ירושה מרובה ב- C ++ היא כלי רב עוצמה, אך מסובך, שלרוב מוביל לבעיות אם לא משתמשים בו בזהירות - בעיות כמו בעיית היהלום.

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

ירושה מרובה ב- C ++

ירושה מרובה היא א תכונה של תכנות מונחה עצמים (OOP) כאשר תת -מחלקה יכולה לרשת יותר מרשת -על אחת. במילים אחרות, כיתת ילדים יכולה להכיל יותר מהורה אחד.

האיור שלהלן מציג ייצוג ציורי של ירושות מרובות.

בתרשים לעיל, כיתה ג יש ל כיתה א ו מחלקה ב ' כהוריו.

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

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

כעת בואו להמחיש את הירושה המרובה ולאמת את סדר הבנייה והשמדת החפצים.

איור קוד של ירושה מרובה

לצורך איור הירושה המרובה, תיכננו בדיוק את הייצוג לעיל ב- C ++. הקוד לתוכנית ניתן להלן.

#לִכלוֹל
באמצעות מרחב שמות std;
מחלקה A // בסיס קלאס A עם בונה והרס
instagram viewer

{
פּוּמְבֵּי:
A () {cout << "class A:: Constructor" << endl; }
~ A () {cout << "class A:: Destructor" << endl; }
};
Class B // Class B עם קונסטרוקטור והרס
{
פּוּמְבֵּי:
B () {cout << "class B:: Constructor" << endl; }
~ B () {cout << "class B:: Destructor" << endl; }
};
מחלקה C: ציבור B, ציבורי A // נגזר בכיתה C יורש את מחלקה A ולאחר מכן את מחלקה B (שימו לב לסדר)
{
פּוּמְבֵּי:
C () {cout << "class C:: Constructor" << endl; }
~ C () {cout << "class C:: Destructor" << endl; }
};
int main () {
C ג;
החזר 0;
}

הפלט שאנו מקבלים מהתוכנית לעיל הוא כדלקמן:

מחלקה ב:: קונסטרוקטור
מחלקה א:: בונה
מחלקה C:: קונסטרוקטור
מחלקה C:: Destructor
מחלקה A:: Destructor
class B:: Destructor

כעת, אם אנו בודקים את הפלט, אנו רואים שהקונסטרוקטורים נקראים לפי סדר B, A ו- C בעוד שהמבנים נמצאים בסדר הפוך. כעת, כאשר אנו מכירים את היסודות של ירושה מרובה, אנו ממשיכים לדון בבעיית היהלום.

בעיית היהלומים, מוסברת

בעיית היהלום מתרחשת כאשר כיתת ילדים יורשת משתי כיתות הורים ששתיהן חולקות כיתה סבא וסבתא משותפת. זה מתואר בתרשים שלהלן:

הנה, יש לנו שיעור יֶלֶד יורש משיעורים אַבָּא ו אִמָא. שתי המעמדות הללו, בתורן, יורשות את המעמד אדם כי גם אבא וגם אמא הם אדם.

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

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

איור קוד של בעיית היהלומים

להלן ייצגנו את הדוגמה לעיל של ירושה בצורת יהלום מבחינה תוכנית. הקוד ניתן להלן:

#לִכלוֹל
באמצעות מרחב שמות std;
אדם בכיתה {// class Person
פּוּמְבֵּי:
אדם (int x) {cout << "אדם:: אדם (int) הנקרא" << endl; }
};
כיתת אב: אדם ציבורי {// אבא בכיתה יורשת אדם
פּוּמְבֵּי:
אבא (int x): אדם (x) {
cout << "אבא:: אבא (int) נקרא" << endl;
}
};
כיתה אמא: אדם ציבורי {// בכיתה אמא ​​יורשת את האדם
פּוּמְבֵּי:
אמא (int x): אדם (x) {
cout << "אמא:: אמא (int) בשם" << endl;
}
};
בכיתה ילד: אבא ציבורי, אם ציבורית {// הילד יורש את אבא ואמא
פּוּמְבֵּי:
ילד (int x): אמא (x), אבא (x) {
cout << "ילד:: ילד (int) שנקרא" << endl;
}
};
int main () {
ילד ילד (30);
}

להלן הפלט של תוכנית זו:

אדם:: אדם (int) נקרא
אבא:: אבא (int) התקשר
אדם:: אדם (int) נקרא
אמא:: אמא (int) התקשרה
ילד:: ילד (int) נקרא

עכשיו אתה יכול לראות את העמימות כאן. בונה כיתת האישיות נקרא פעמיים: פעם אחת כאשר האובייקט של מחלקת האב נוצר ולאחר מכן כאשר האובייקט של מחלקת האם נוצר. המאפיינים של מחלקת ה- Person עוברים בירושה פעמיים, מה שמעורר עמימות.

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

עכשיו אם הבנת את הבעיה נכון, בואו נדון בפתרון לבעיית היהלום.

כיצד לתקן את בעיית היהלומים ב- C ++

הפתרון לבעיית היהלום הוא שימוש ב- וירטואלי מילת מפתח. אנו הופכים את שתי כיתות ההורים (שירשות מאותה כיתה סבא וסבתא) לשיעורים וירטואליים על מנת להימנע משני עותקים של כיתת הסבא בשיעור הילדים.

בואו נשנה את האיור לעיל ונבדוק את הפלט:

איור קוד לתיקון בעיית היהלומים

#לִכלוֹל
באמצעות מרחב שמות std;
אדם בכיתה {// class Person
פּוּמְבֵּי:
Person () {cout << "Person:: Person () שנקרא" << endl; } // קונסטרוקטור בסיס
אדם (int x) {cout << "אדם:: אדם (int) הנקרא" << endl; }
};
אבא בכיתה: אדם ציבורי וירטואלי {// אבא בכיתה יורש את האדם
פּוּמְבֵּי:
אבא (int x): אדם (x) {
cout << "אבא:: אבא (int) נקרא" << endl;
}
};
אמא בכיתה: אדם ציבורי וירטואלי {// כיתה אמא ​​יורשת את האדם
פּוּמְבֵּי:
אמא (int x): אדם (x) {
cout << "אמא:: אמא (int) בשם" << endl;
}
};
ילד בכיתה: אבא ציבורי, אמא ציבורית {// כיתה הילד יורש את אבא ואמא
פּוּמְבֵּי:
ילד (int x): אמא (x), אבא (x) {
cout << "ילד:: ילד (int) שנקרא" << endl;
}
};
int main () {
ילד ילד (30);
}

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

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

הפלט של הקוד לעיל ניתן להלן:

אדם:: אדם () התקשר
אבא:: אבא (int) התקשר
אמא:: אמא (int) התקשרה
ילד:: ילד (int) נקרא

כאן אתה יכול לראות כי בונה האדם בכיתה נקרא רק פעם אחת.

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

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

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

בדוגמה שלמעלה, הילד בכיתה מתקשר ישירות לבנאי הבסיס של איש הכיתה.

קָשׁוּר: מדריך למתחילים לספריית התבניות הסטנדרטיות ב- C ++

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

בעיית היהלומים ב- C ++, נפתרה

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

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

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

לַחֲלוֹקצִיוּץאימייל
10 הפרויקטים הטובים ביותר למתחילים למתכנתים חדשים

רוצה ללמוד תכנות אבל לא יודע מאיפה להתחיל? פרויקטי תכנות מתחילים והדרכות אלה יתחילו אותך.

קרא הבא

נושאים קשורים
  • תִכנוּת
  • C תכנות
על הסופר
צוות MUO

הירשם לניוזלטר שלנו

הצטרף לניוזלטר שלנו לקבלת טיפים, סקירות, ספרים אלקטרוניים בחינם ומבצעים בלעדיים!

לחצו כאן להרשמה