לוגו אתר Fresh          
 
 
  אפשרות תפריט  ראשי     אפשרות תפריט  צ'אט     אפשרות תפריט  מבזקים     אפשרות תפריט  צור קשר     חץ שמאלה ‎print ‎"Hello World!"; if‎ ‎not rules.‎know ‎then rules.‎read(); חץ ימינה  

לך אחורה   לובי הפורומים > מחשבים > תכנות ובניית אתרים
שמור לעצמך קישור לדף זה באתרי שמירת קישורים חברתיים
תגובה
 
כלי אשכול חפש באשכול זה



  #3  
ישן 23-01-2010, 13:17
  Dark Knight Dark Knight אינו מחובר  
 
חבר מתאריך: 30.07.05
הודעות: 949
שלח הודעה דרך ICQ אל Dark Knight
בתגובה להודעה מספר 1 שנכתבה על ידי asia שמתחילה ב "שאלות בC\C++"

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

לכן, כמו שניתן להגדיר מצביע למקום בזיכרון ששומר מידע (int, double, מחרוזת...), ניתן להגדיר גם מבציע למקום בזיכרון בו רשומה פונקציה. זה למעשה מצביע לפונקציה.

מצביעים לפונקציות שימושיים מאד ב-C כאשר עובדים עם טיפוסי נתונים מופשטים (ADT).
למשל את רוצה ליצור טיפוס של רשימה מקושרת. במקרה כזה יש לך 2 אפשרויות:
א) להעתיק את הקוד שלך הרבה פעמים עם שינויים קטנים, וליצור רשימה מקושרת שיכולה להכיל int, רשימה שיכולה להכיל double, רשימה שיכולה להכיל.........
ב) ליצור רשימה חסרת טיפוס - כזו שמחזיקה בכלל *void, כלומר מצביע למקום בזיכרון בלי ידע מקדים על הטיפוס שלו, ובעצם לשלוח לרשימה שלך את הפונקציות המתאימות לטיפול באיברים:
פונקציה שיוצרת עותק איבר (לצורך הכנסה)
פונקציה שמשחררת את זיכרון האיבר (לצורך הוצאה)
פונקציה שמשווה בין 2 איברים (לצורך חיפוש)
ועוד פונקציות שימושיות כאלו...

כאשר תוסיפי איבר לרשימה, למשל, תשתמשי בפונקצית ההעתקה ע"מ ליצור עותק של האיבר המקורי שקיבלת לתוך פונקצית ההוספה, ותזיני את הכתובת של מה שנוצר לתוך הרשימה.

לדוגמא יש לך רשימה כזו, ואת רוצה לעבוד עם int, אז את תיצרי 3 פונקציות:
קוד PHP:
 // List element type
typedef voidElement;
// Copy function type: receive an element and allocate a copy of it
typedef Element (*CopyFunction)(Element source);
// Free function type: receive an element and free it's memory
typedef void (*FreeFunction)(Element elem);
// Compare function type: given two elements return true if elements are equal or false otherwise
typedef bool (*CompareFunction)(Element e1Element e2);

/* #####        Integer list functions        ##### */

Element IntCopy(Element source)
{
    
int *src = (int *)source;
    
int *copy = (int *)malloc(sizeof(int));
    if (
copy != NULL) {
        *
copy = *src;
    }
    return (
Element)copy;
}

void IntFree(Element elem)
{
    
int *src = (int *)elem;
    
free(src);
}

bool IntCompare(Element e1Element e2)
{
    
int *src1 = (int *)e1;
    
int *src2 = (int *)e2;
    return (*
src1 == *src2);



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

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

קוד PHP:
 // A comparison function type:
// Returns -1 if e2 > e1
// Returns 0 if e1 == e2
// Returns 1 if e1 > e2
typedef int (*ComparingFunction)(void *e1void *e2);

// The sorting function
void Sort(void *Array[], ComparingFunction cmp);

// Usage:
char *Text[] = { "Hello""My""Name""Is""Agent""Smith" };

int MyStrcmp(void *e1void *e2)
{
    
char *s1 = (char*)e1;
    
char *s2 = (char*)e2;
    return 
strcmp(s1s2);
}

Sort(TextMyStrcmp); 
_____________________________________
חתימתכם הוסרה כיוון שלא עמדה בחוקי האתר. לפרטים נוספים לחצו כאן. תוכלו לקבל עזרה להתאמת החתימה לחוקים בפורום חתימות וצלמיות.


נערך לאחרונה ע"י Dark Knight בתאריך 23-01-2010 בשעה 13:29.
תגובה ללא ציטוט תגובה עם ציטוט חזרה לפורום
  #4  
ישן 24-01-2010, 00:19
צלמית המשתמש של Narxx
  משתמש זכר Narxx Narxx אינו מחובר  
 
חבר מתאריך: 21.12.04
הודעות: 30,021
בתגובה להודעה מספר 1 שנכתבה על ידי asia שמתחילה ב "שאלות בC\C++"

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

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

דוגמא:
קוד PHP:
 #include <iostream>
using namespace std;

void func1(int&);

int main()
{
    
int x;
    
5;
    
cout << "x's address is: " << &<< endl;
    
func1 (x);
    
cin >> x;
    return 
0;
}

void func1 (inty)
{
    
cout << "y's value is: " << << ", and y's address is: " << &<< endl;


ניתן לראות שאני שולח את המשתנה בצורה רגילה לפונקציה, אבל מקבל בפונקציה By Refernce ולא By Value (כלומר - אין העתקה של התוכן, אלא העברה של המשתנה עצמו לפונקציה).
כאשר עובדים עם אובייקטים קצת יותר מסובכים אשר מכילים בנאים כמו Copy Constructor - ההבדל בין שליחה By Value לבין שליחה By Reference יכולה להיות משמעותית מאוד.
_____________________________________
בברכה, מתן.
www.MatanNarkiss.com

תגובה ללא ציטוט תגובה עם ציטוט חזרה לפורום
תגובה

כלי אשכול חפש באשכול זה
חפש באשכול זה:

חיפוש מתקדם
מצבי תצוגה דרג אשכול זה
דרג אשכול זה:

מזער את תיבת המידע אפשרויות משלוח הודעות
אתה לא יכול לפתוח אשכולות חדשים
אתה לא יכול להגיב לאשכולות
אתה לא יכול לצרף קבצים
אתה לא יכול לערוך את ההודעות שלך

קוד vB פעיל
קוד [IMG] פעיל
קוד HTML כבוי
מעבר לפורום



כל הזמנים המוצגים בדף זה הם לפי איזור זמן GMT +2. השעה כעת היא 19:11

הדף נוצר ב 0.06 שניות עם 10 שאילתות

הפורום מבוסס על vBulletin, גירסא 3.0.6
כל הזכויות לתוכנת הפורומים שמורות © 2024 - 2000 לחברת Jelsoft Enterprises.
כל הזכויות שמורות ל Fresh.co.il ©

צור קשר | תקנון האתר