copy constructor

ilankt

New member
copy constructor

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

vinney

Well-known member
כשמו כן הוא

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

vinney

Well-known member
טוב, אנסה

קורה לפעמים שצריכים להעביר ערך של משתנה אחד למשתנה אחר מאותו סוג (השמה). עבור טיפוסים סטנדרטים ונגזרות שלהם, הקומפיילר יודע לטפל בבעיה. מה קורה עם מחלקות שיצרנו? יש את פעולת ברירת המחדל - הקומפיילר מעתיק את הזכרון שהוקצה לאובייקט אחד לזכרון שהוקצה לאובייקט אחר. זה טוב לנו? לפעמים, כשכל המשתנים במחלקה פשוטים. כשיש לנו מצביעים/אובייקטים וכו וכד', זה לא יתאים. אז הקומפיילר מצפה שאנחנו נכתוב את פעולת ההשמה במפורש. copy constructor זה בדיוק זה. הוא מקבל את מופע המקור, הוא עצמו שייך למופע היעד, ובאחריותו לבצע העברת המידע.
 

ilankt

New member
תודה

איך ממשים ב ++C? סליחה שאני משגע אותך
 

vinney

Well-known member
ככה

class a { public: a(){ m_a = 0;}; // default constructor a(a& i_a){ m_a = i_a.m_a; }; // copy constructor private: int m_a; };​
 

DadleFish

New member
כמה הערות

מומלץ להגדיר את ה-reference עם const למניעת שינוי של ה-RHS (שזה ה-Right Hand Side) של המשוואה. למשל, קח את הקוד הבא:
class A { public: A(int i_n) : n(i_n) {} A(A &rhs) { n = rhs.n; rhs.n = 5; } private: int n; }; int main() { A a(10); A b = a; return 0; }​
במקרה הנ"ל, בסוף התהליך, b.n יכיל 10 (שהיה הערך של a.n), ואילו a.n יכיל 5, כי שינינו אותו (בטעות, נניח) בתוך ה-Copy ctor של A. עדיף להגדיר את ה-Copy Ctor בצורה הבאה, שתמנע שינוי של ה-RHS:
... A(const A &rhs) {...} ...​
שנית, Copy Ctor לא משמש להשמות - אלא ליצירת אובייקט חדש תוך התבססות על אובייקט קיים. למשל:
(1) A a = b; (2) A a(b); (3) A a; a = b​
במקרים 1 ו-2 יופעל Copy constructor (אני מניח ש-b הוא מטיפוס A כמובן). במקרה 3 יופעל תחילה Default constructor, ולאחר מכן יופעל ה-Assignment operator, שאפשר להגדירו כך:
class A { ... A &operator =(const A &a); ... };​
...מה שמביא אותי לנקודה האחרונה - אם הגדרת Copy Constructor, כנראה שאתה צריך גם Assignment operator. זה כמעט תמיד נכון, ובכלל עדיף לעשות פונקציה אחת שקוראים לה משתי הפונקציות - מה-copy ctor ומה-assignment.
 

IdanR

New member
זה בדיוק כמו constructor רגיל,

רק שכפרמטר הוא מקבל reference לאובייקט מאותו סוג. ואז, אם יש לך מחלקה מסוג CPoint נגיד, אתה יכול לעשות דבר כזה:
CPoint pntFirst(1, 2); CPoint pntCopy = pntFirst;​
שזה טריק נחמד, רק שאפשר קצת להתבלבל ולחשוב בטעות שיש לאובייקט operator overloading לאופרטור השמה.
 

IdanR

New member
זו טעות לחשוב ..

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

vinney

Well-known member
השימוש ב CC הוא בcontainers

בעיקר ובהעברת פרמטרים וכו
 

vinney

Well-known member
בSTLים

אם אתה מגדיר משהו כזה
class A; set<A> A_set​
אז SET מצפה שלA יהיה copy constructor.
 

voguemaster

New member
תן הסבר מלא! ../images/Emo3.gif

ולמה הוא מצפה שיהיה copy ctor ? הסיבה היא שמה שמוכנס לתוך ה-CONTAINER הוא עותק של האובייקט. לכן, STL מניחה שיש copy ctor למחלקה A. אם לא מימשת אחד, ++C תהיה יותר משמחה לממש לך אחד (וכידוע, בהרבה מקרים זה אסון
).
 

ilankt

New member
ואם לא ממשים CC

ומעבירים לפונקציה אובייקט לא by reference, אז C++ יצור אובייקט חדש? אם כן איך ה ctor וה dtor יעבדו?
 

® רן

New member
אם לא ממשים CC

אז שפה עושה את זה אוטומטית עבורך. הבעיה היא, שהיא עושה את זה בצורה פשטנית שלא תמיד מתאימה. אם ה class מכיל רק טיפוסי נתונים פשוטים כמו int-ים, זה בסדר. אם הוא מכיל הצבעות לאובייקטים אחרים (פוינטרים או reference-ים), ה CC הדפולטי יעתיק את המצביע ולא את תוכנו. דוגמא:
class A {}; class B { public: A* a; }; int main() { B firstB; firstB.a = new A(); B secondB = firstB; }​
בסיום הפונקציה, המצביע שב secondB מצביע לאותו A שמוצבע עם ע"י firstB. כדי לפתור את הבעיה צריך לממש Copy Constructor:
B::B() {}; // regular constructor B::B (B& other) { // copy constructor a = new A (other.a); }​
וכמובן שאם A הוא מחלקה לא טרויאלית אז כדאי שגם לו יהיה CC. אגב, שאלה בנושא הזה היינו שואלים בראיונות עבודה באחד ממקומות העבודה הקודמים שלי.
 

DadleFish

New member
עוד שאלה שלא רלוונטית לכלום לדעתי.

אין כמו שאלות טריוויה ו/או שאלות פינות ב-++C בראיונות עבודה כדי לתת סיפוק זדוני לשואל ולא להעיד שום דבר על הנשאל.
 

® רן

New member
לא מסכים איתך

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