4.3.3. Upcasting, Downcasting

Casting (המרה): המרת coercion של אובייקט ממחלקה נגזרת לאובייקט ממחלקת הבסיס.

Up-casting: המרת מצביעים במעלה היררכית ההורשה (למשל, המרת מצביע מסוג עובד למצביע מסוג בן אדם).

Up-casting של this מתבצע באופן אוטומטי בכל פעם שאנחנו משתמשים במתודה שנורשה ממחלקה אחרת.



Emploee E;

Manager M;

M.is_manager_of(E)      // Type of this is Manager*,

                  // No casting occurs

M.raise_salary(10);     // Type of this is Employee*

                  // in raise_salary.

                  // Up casting must occur

Down-casting: המרת מצביעים במורד גרף ההורשה. המרה זו חייבת להתבצע על ידי הוראה מפורטת. המרה זו נעשית רק במקרים מיוחדים – זו אינה המרה שנרצה לרוב לבצע.

Employee  E, *pE;

Manager   M, *pM;

pE = &M;                // OK: implicit upcasting.

M = *pE;                // Error: implicit downcasting is not allowed

// explicit down casting:

M = *(Manager *)pE;                 // deprecated syntax

M = *static_cast<Manager*>pE;       // recommended syntax

נשים לב למה שכתוב בקוד – מומלץ להשתמש בהמרה על ידי static_cast, ולא בתחביר השני, המיועד בעיקר כדי לתמוך בקוד C ישן.

המרת down-casting עשויה להיות לא חוקית. ניתן לבצע המרת down-casting בטוחה על ידי dynamic_cast. לדוגמא:

Manager &mRef = dynamic_cast<Manager &>eRef;

במידה ואי יהיה אפשר לבצע את ההמרה, שפת C++ תזרוק חריגה מסוג bad_cast.

נביט בדוגמא לתוכנית בדיקה האם אובייקט הוא מסוג מסוים:

#include <iostream>

#include <cstdlib>

using namespace std;

class A

{

public:

    virtual void f() {};

};



class B : public A

{

public:

    void f() {};

};

class C

{

public:

    void f() {};  

};

int main()

{

      A *a1 = new A;

      A *b1 = new B;

      C *c1 = new C;

      if (B* ref1 = dynamic_cast<B*>(b1))

            cout << "b1 is B" << endl;

      else

            cout << "b1 isn't B" << endl;

      if (C* ref1 = dynamic_cast<C*>(b1))

            cout << "b1 is C" << endl;

      else

            cout << "b1 isn't C" << endl;

      return 0;

}

פלט התוכנית:

b1 is B

b1 isn't C

  • נשים לב שבתנאי ה-if היה = בודד. זו איננה שגיאה, אלא התחביר. אנחנו בודקים האם ref1 למשל הוא NULL או לא למעשה.

מאת: ניצן

Borland style vptr

לפי מה שאני מכיר:
"חסרון בגישה זו: גם כאשר איננו משתמשים ב-dynamic binding – אנחנו משלמים במקום"
לא נכון , עבור מחלקה A שאין לה מתודות דינמיות לא יווצר כלל המצביע, ולמשל עבור מחלקה B שיורשת מA פשוט נוסיף בהתחלה את המצביע, ואחרי הבלוק של A את שאר האינפורמציה של B . וככה לא משלמים על מה שלא משתמשים ועקרונות C++ נשמרים.
מה שכן באמת הcasting קצת יותר מסובך....
שיתוף:
| עוד