מצביעים לפונקציות ב-C

The Mystique

New member
מצביעים לפונקציות ב-C

למה הם משמשים ? ועד כמה הם שימושיים ?
 

עידית_

New member
הנה שימוש לדוגמה:

לדוגמה: אתה מממש איזה מבנה נתונים ממוין, אבל הנתונים בו יכולים להיות מסוגים שונים. כלומר פעם אתה רוצה להשתמש בו בשביל להחזיק מחרוזות, ופעם בשביל מספרים, ופעם בשביל נתונים מטיפוס של איזה class שאתה המצאת... איך תכתוב את פונקציית המיון? כלומר פונקציה שמשווה בין שני נתונים וקובעת "מי קודם"? הרי יש אלגוריתם אחר לכל סוג של נתונים. במקרה כזה אתה יכול לכתוב 3 פונקציות מיון שונות, ואז לכתוב עבור המבנה נתונים פונקציית מיון גנרית, שמקבלת כפרמטר מצביע לפונקציית המיון המתאימה, ומפעילה אותה. וכמובן שזה גם פתרון נוח כיוון שזה נותן לך יכולת הרחבה - אם בעתיד תרצה לשים במבנה הנתונים טיפוס מסוג חדש - תצטרך רק לכתוב פונקציית מיון גם עבורו, ולא תצטרך לשנות בכלל את המימוש הכללי של מבנה הנתונים... זו רק דוגמה אחת שקופצת לי לראש. מן הסתם יש עוד שימושים. באופן כללי יותר - זה שימושי כשאתה רוצה ליצור תבנית (pattern) כללית, שניתן יהיה להשתמש בה במקרים רבים מבלי לשנותה. זה נותן לך גנריות לא רק בנתונים עצמם, אלא גם גנריות של אלגוריתמים.
 

The Mystique

New member
שינויים עתידניים

כמו שאני מבינה, פונקציית המיון הגנרית משמשת כתוכנית מתאמת בין מבנה הנתונים ופונקציות המיון השונות ? כך שאם ארצה להוסיף פונקציית מיון חדשה למבנה נתונים חדש כל מה שעליי לעשות הוא להוסיף: 1. מבנה הנתונים. 2. שליחת לפונקציית מיון חדשה בפונ´ המתאמת. 3. כתיבת פונ´ מיון למבנה הנתונים החדש. אכן כך ? המצביעים לפונ´ למעשה נימצאים בתוך הפונ´ המתאמת ? קיים מצב שבו ניתן להשתמש במצביעים לפונ´ ללא פונ´ מתאמת בינהן ?
 

עידית_

New member
לא כל כך הבנתי אותך, אז אני אנסה

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

The Mystique

New member
Generic

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

עידית_

New member
כן, זה בעיקר עניין של עיצוב

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

erezsh

New member
כמה שימושים

למצביע לפונקציה יש כמה שימושים. 1) שימוש עיקרי הוא העברת הפונקציה כפרמטר. נגיד יש פונקציה בשם DO, שאתה רוצה שתבצע את הפונקציה (מסיבות שלא אפרט), הדרך היחידה היא להשתמש במצביע. 2) קריאת ערך הפונקציה שהוחזר כמה פעמים מבלי לבצע אותה שוב ושוב. 3) מתכנתים מתקדמים עשויים להשתמש בזה על מנת להוסיף לפונקציה פקודות של קוד מכונה. לשם כך הם צריכים לדעת את הכתובת של תחילת הפונקציה.. יש עוד הרבה שימושים שאני כרגע לא חשוב עליהם...
 

ihovav

New member
תשובה

כמו שכתבה עידית: אם אתה רוצה ליצור מבנה נתונים(STRUCTURE) ש"יודע" לטפל בכמה סוגי מידע הסבר קובץ הדוגמא: זה מבנה שמכיל למעשה נתונים על צורות (נקודה, קו, מרובע-מלבן ופוליגון) ומכיל גם את ה"טיפולים" בצורות האלו הפונקציות שבמבנה מקבלות אותו סוג נתונים אבל מטפלות בנתונים בצורה שונה לכל צורה כאשר יוצרים צורה - מאתחלים את השדות של הפונקציות ע"פ סוג הצורה ואז לא צריך להפעיל כל פעם פונקציה מסויימת על צורה מסויימת - אלא מפעילים את ה"שדה" הגנרי של הצורה והוא מטפל בה כמו שצריך לדוגמא : שמירת צורה - בנקודה - צריך לשמור רק X ו Y אבל בפוליגון - צריך לשמור את כל הנקודות וגם את ה CENTER של הצורה - אבל בגלל שהפונקציות של כל צורה "מחוברות" אליה - צריך פשוט לקרוא לפונקצית "SAVE" על כל צורה והיא נשמרת כמו שצריך זו רק דוגמא אחת לשימוש בפוינטרים לפונקציות - יש הרבה נוספות חובב
 

ihovav

New member
תוספות :

1-> השמות של השדות במבנה של הפונקציות בקובץ המצורף הם למעשה טייפדפים של פוינטרים לפונקציות 2-> אם את מכירה CPP - זה כמו ליצור תת מחלקה שממנה יורשים כל המחלקות בתכנית וכל המטודות הרלוונטיות למחלקות מופיעות בתת-המחלקה כווירטואליות, ואז מתבצע פולימורפיזם בזמן הפעלת מטודה מסויימת על אובייקט מסויים
 

The Mystique

New member
תכנות מונחה עצמים

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

ihovav

New member
CPP זה סי פלוס פלוס...

אני מתפלא שאת מבינה בירושות אבל לא יודעת מה זה CPP... לא משנה בכל מקרה הקוד הזה הוא ב C טהור והמטרה שלו היא לאפשר שדה גנרי בתוך STRUCT שיוכל לטפל בכל הפעולות המשותפות לאותו ה STRUCT זה למעשה מה שמכונה "ירושה" ופולימורפיזם בשפות ה OBJECT ORIENTED
 

The Mystique

New member
גם זה קורה

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

ihovav

New member
תגובה :

CPP דומה בהרבה מובנים לעדה - אבל יש כמה הבדלים כמו : ב CPP מאפשרים ירושה מרובה - זה יוצר הרבה בעיות שצריך להתמודד איתן אני אשמח לעזור לך ללמוד - אבל אני באמת לא מכיר את עדה ככה שאני לא יודע מה את יודעת ומה לא אני אשמח לעזור בשאלות ממוקדות ב CPP ובכל דבר שידרש
 

The Mystique

New member
תודה ../images/Emo41.gif

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

ihovav

New member
תיקון (כמו שביקשת)

1 -> שהם הוא י.חובב 2 -> CPP זה C++ ולהיפך
 
למעלה