سؤال عن ال enheritance,class,object,pointer في ++C

السلام عليكم في الحقيقة شاهدت فيديو على اليوتيوب و لم افهم بعض الأشياء و هذا ما جعلني اطرح عليكم المشكلة التي لم افهمها عسى احدكم يقدر يوضحلي الفكرة :

في الأول نفترض ان لدينا كلاس اسمه test1 و كلاس اخر اسمه test2 وهذا الاخير ورث جميع خصائص الكلاس test1 ثم في main قمنا بعمل object من نوع test2 هكذا

;test2 ot

صار لدينا object ot من الكلاس test2 ثم عملنا pointer من نوع test1 واشرناه الى ال object ot الذي هو من نوع test2 (الي ورث خصائص test1) هكذا :

;test1 *pt = &ot

السؤال كيف هذا ممكن ؟ لان صاحب الفيديو عمل هذا الشي و اشتغل البرنامج اليس من الفروض ان ال pointer يكون من نفس نوع الكلاس الي يؤشر عليه اذا من الممكن احدكم يفسرلي الفكرة بوضوح و ما الفرق بين هاذين السطرين ؟

;test1 *pt = &ot

;test2 *pt = &ot (من المفروض ان تكون هكذا العبارة الصحيحة او لا)

و شكرا لكم

يرجى الدخول لحسابك أو تسجيل حساب لتستطيع إضافة تعليق
حساب جديد دخول

التعليقات

السلام عليكم أخي العزيز

لنأخذ الموضوع بشكل عملي أكثر

لنفترض أننا نملك class يسمى employee

class employee{
 public :
    void printName(){cout<<"employee class" <<endl;
  }
}

و لدينا class يسمى manager

class manager : public employee{
 public :
    void printName(){cout<<"manager class" <<endl;
  }
   void printAge(){cout<<"manager Age" <<endl;
  }

}

لنـأتي للتطبيق الآن

int main () {
  employee *e = new manager();//لا مشكلة لأنه كما نعلم بأن كل مدير عبارة عن عامل
  e->printName();// ستقوم بطباعة "employee class" ( مشكلة )
  e->printAge(); //خطأ لأنه لايوجد دالة بهذا الأسم, لذلك يمكن أن نستنتج بأنه يمكنه أن يرى جزء الأب فقط و لايمكنه الوصول إلى دوال أو متغيرات الأبناء

  manager *m = new employee(); // خطأ لأنه يستحال أن يكون كل عامل مدير
}

اذاً كما نلاحظ أنه يمكننا إنشاء متغير base من derived و لكن العكس لايصح.

حسناً الآن هناك مشكلة لماذا يطبع "employee class" بدلاً من طباعة "manager class" .

في هذه الحالة يكون الربط بين object و الدوال عند ما يسمى ب ' compile time ' وتحدد الدالة على حسب نوع المتغير الذي هو في هذه الحالة ' employee ' .

لذلك هناك ما يسمى ب 'virtual functions ' التي تقوم بتأجيل عملية الربط إلى ما يسمى ب ' run time ' و تحدد الدالة على حسب نوع المتغير المربوط به الذي هو في هذه الحالة ' manager '.

لنأخذ مثال يشرح إستخدام virtual

class animal{
 public :
    virtual void printName(){cout<<"I am an animal" <<endl;
  }
}
class cat: public animal{
 public :
    void printName(){cout<<"I am a cat" <<endl;
  }

}

نلاحظ أن كلمة virtual تستخدم فقط مع base class.

الآن لنفترض أن لدينا الدالة التالية :

void name (animal *a){
   a->printName();
}

و لدينا

{
    animal an;
    cat c;
    name(&an);
    name(&c);
}

الآن بدون استخدام virtual سيكون المطبوع في الحالتين

"I am an animal"

ولكن مع استخدام virtual ستجد أنه لاحظ أن النداء الثاني كان من object من نوع cat فكانت الطباعة

"I am an animal"

"I am a cat"

أعتذر عن التعليق السابق لأنه نزل بالخطأ و لم أستطع تعديله.

أرجو لك التوفيق و أن أكون قد وفقت في الشرح.

والله ولي التوفيق.

شكرا لك اخي على التفسير العميق :)

wada3n أضف ردا

جرب العكس تجد الإجابة صديقي

ceferinoj171 أضف ردا

شكرا أخي على تفاعلك

لكن في السطر cout<<pt.r //لا يمكن لان البروبرتي ار خاصة فقط بتست2 //

اولا يجب ان تكتب cout << pt - > r ولكن لا علينا اضن انك غفلت عن ذلك صديقي :)

المشكلة اني لم افهم لماذا لا يمكن ذلك اليس المؤشر pt يؤشر على ot الذي هو objet من test2 من المفروض ان له الامكانية ان يستخدم r اذا لك تفسير منطقي لذلك المرجوا ان تكتبه و شكرا مرة اخرى للتفاعل

wada3n أضف ردا

أهلا أخي

أجل لقد قمت متعمدا بذلك حتى أريك أنك لاتستطيع الولوج إلى الخاصية r من خلال مؤشر نحو كائن خاص بها / كانت ككومنت صديقي

لا يمكن أخي لأن أساسا الأوبجكت test1 لايملك الخاصية r وأنت عندما قمت بعمل مؤشر نحو الكائن الذي ورث منه أنت كأنك أخذت فقط المشتركات بينهما / وكما وضعت في الصورة العكس لايمكن لأن التست2 لايمكن أن يحتوى في كائن من تست 1 هل فهمتني ؟

بالمناسبة هذه من unsafety في c++ حسب معرفتي لو جربتها في لغة مثل rust لم تتمكن من ذلك

السلام عليكم أخي العزيز

لنأخذ الموضوع بشكل عملي أكثر

لنفترض أننا نملك class يسمى employee

class employee{
 public :
  void printName(){cout<<"employee class" <<endl;
  }
}

و لدينا class يسمى manager

class manager:public employee {

  public : void printName(){ cout << "manager class" << endl;{ }