سؤال عن ال 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"

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

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

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

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