C++-da Upcasting və Downcasting

giriş

Yuxarıdan çıxarma və aşağı salma C ++ dilinin vacib bir hissəsidir. Yuxarıdan çıxarma və aşağı salma, sadə bir proqramla mürəkkəb proqramlar qurma imkanı verir sintaksis. Polimorfizmdən istifadə etməklə əldə edilə bilər.

C ++, bir törəmə sinif göstəricisinə (və ya) icazə verir arayış) əsas sinif göstəricisi kimi qəbul edilməlidir. Bu razıdır.

Aşağı tökmə, əsas sinif göstəricisinin (və ya istinadın) əldə edilmiş sinif göstəricisinə çevrilməsindən ibarət olan əks bir prosesdir.

C ++ Yuxarıdan və Yuxarıdan açıqlama, fərqli məlumat tiplərinin sadə bir yayımı kimi başa düşülməməlidir. Böyük qarışıqlığa səbəb ola bilər.

Bu mövzuda aşağıdakı sinif iyerarxiyasından istifadə edəcəyik:

C ++ tökmə və aşağı tökməPin

Gördüyünüz kimi menecer və katib hər ikisi işçidir. Hər ikisi də Şəxsdir. Bunun mənası nədi? Bu, Manager və Clerk siniflərinin Person sinifinin xüsusiyyətlərini miras alan Employee sinifinin xüsusiyyətlərini miras alması deməkdir.

Məsələn, həm Menecerin həm də Katibin Ad və Soyadla təyin olunduğunu, əmək haqqının olduğunu göstərməyimizə ehtiyac yoxdur; onlar haqqında məlumat göstərə və maaşlarına bonus əlavə edə bilərsiniz. Bu xassələri yalnız bir dəfə İşçi sinifində göstərməliyik:

Eyni zamanda, Menecer və Katib dərsləri fərqlidir. Menecer hər müqavilə üçün komissiya haqqı alır və Katib öz meneceri haqqında məlumatlara malikdir:

Yoxla

#include <iostream>
using namespace std;

class Person
{
	//content of Person
};


class Employee:public Person
{
public:
	Employee(string fName, string lName, double sal)
	{
		FirstName = fName;
		LastName = lName;
		salary = sal;
	}
	string FirstName;
	string LastName;
	double salary;
	void show()
	{
		cout << "First Name: " << FirstName << " Last Name: " << LastName << " Salary: " << salary<< endl;
	}
	void addBonus(double bonus)
	{
		salary += bonus;
	}
};

class Manager :public Employee
{
public:
	Manager(string fName, string lName, double sal, double comm) :Employee(fName, lName, sal)
	{
		Commision = comm;
	}
	double Commision;
	double getComm()
	{
		return Commision;
	}
};

class Clerk :public Employee
{
public:
	Clerk(string fName, string lName, double sal, Manager* man) :Employee(fName, lName, sal)
	{
		manager = man;
	}
	Manager* manager;
	Manager* getManager()
	{
		return manager;
	}
};

void congratulate(Employee* emp)
{
	cout << "Happy Birthday!!!" << endl;
	emp->addBonus(200);
	emp->show();
};

int main()
{
    //pointer to base class object
    Employee* emp;
    
    //object of derived class
    Manager m1("Steve", "Kent", 3000, 0.2);
    Clerk c1("Kevin","Jones", 1000, &m1);
    
    //implicit upcasting
    emp = &m1;
    
    //It's ok
    cout<<emp->FirstName<<endl;
    cout<<emp->salary<<endl;
    
    //Fails because upcasting is used
    //cout<<emp->getComm();
    
    congratulate(&c1);
    congratulate(&m1);
    
    cout<<"Manager of "<<c1.FirstName<<" is "<<c1.getManager()->FirstName;
}

 

Menecer və Katib həmişə İşçilərdir. Üstəlik, İşçi Şəxsdir. Bu səbəbdən Menecer və Katib də Şəxsdir. Əvvəlcədən və aşağı məzmunu öyrənməyə başlamazdan əvvəl bunu anlamalısan.

Həm tökmə, həm də yıxılma, obyekti öz-özünə dəyişdirmir. Yuxarıdan və ya aşağıdan istifadə edərkən bir obyekti müxtəlif yollarla “etiketləyin”.

YERLƏNMƏ

Yuxarıdan yayımlama, bir göstəricinin yaradılması və ya əsas sinif göstəricisi kimi əldə edilən sinif obyektinə istinadın yaradılmasıdır. Əl ilə hazırlanmanıza ehtiyac yoxdur. Yalnız əsas sinif göstəricisinə əldə edilmiş sinif göstəricisini (və ya istinad) təyin etməlisiniz:

//pointer to base class object
Employee* emp;
//object of derived class
Manager m1("Steve", "Kent", 3000, 0.2);
//implicit upcasting
emp = &m1;

Yuxarıdan istifadə edərkən, obyekt dəyişmir. Buna baxmayaraq, bir obyekti yıxdığınız zaman yalnız üzvə girə biləcəksiniz funksiyaları və əsas sinifdə müəyyən edilmiş məlumat üzvləri:
//It's ok
emp->FirstName;
emp->salary;
//Fails because upcasting is used
emp->getComm();

Yuxarıdan istifadə nümunəsi

Yuxarıdan yayımlamanın ən böyük üstünlüklərindən biri, eyni baza sinifindən çıxarılan bütün siniflər üçün ümumi funksiyalar yazma qabiliyyətidir. Bir nümunəyə baxın:

void congratulate(Employee* emp)
{
	cout << "Happy Birthday!!!" << endl;
	emp->show();
	emp->addBonus(200);
};

Bu funksiya Employee sinifindən əldə edilən bütün siniflərlə işləyəcəkdir. Menecer və Şəxs tipli obyektlərlə çağırdığınız zaman avtomatik olaraq İşçi sinifinə yüksəldiləcəklər:
//automatic upcasting
congratulate(&c1);
congratulate(&m1);

Bu proqramı çalışdırmağa çalışın:

Ad günün mübarək!!!
Ad: Kevin Soyad: Jones
Ad günün mübarək!!!
Ad: Steve Soyad: Adı Kent

Yuxarıdan yayımlamanın virtual funksiyalarla necə istifadə olunacağının bir nümunəsi “C ++ Polimorfizm”Mövzusundadır.

Yaddaş düzeni

Bildiyiniz kimi, çıxarılan sinif əsas sinifin xüsusiyyətlərini genişləndirir. Bu, əldə edilən sinifin xüsusiyyətlərə (məlumatlara) sahib olması deməkdir üzvlər və üzv funksiyaları) əsas sinifin və yeni məlumat üzvlərini və üzv funksiyalarını müəyyənləşdirir.

Baxın yaddaş düzeni İşçi və menecer siniflərindən:

C ++ tökmə və aşağı tökməPin

Əlbətdə ki, bu model obyektlər üçün yaddaş tərtibatının sadələşdirilmiş görünüşüdür. Bununla birlikdə, əsas sinif istifadə etdiyiniz həqiqəti təmsil edir göstərici çıxarılan sinfin bir obyektini göstərmək üçün yalnız əsas sinifdə (yaşıl sahə) müəyyən edilmiş elementlərə daxil ola bilərsiniz. Bir baza istifadə edərkən əldə edilən sinifin elementləri (sarı sahə) əlçatan deyil sinif göstəricisi.

YÜKLƏMƏ

Aşağı tökmə, yuxarı yayım üçün əks bir prosesdir. Əsas sinif göstəricisini əldə edilmiş sinif göstəricisinə çevirir. Aşağı tökmə əl ilə aparılmalıdır. Bu, açıq tip yayımlamalı olduğunuz deməkdir.

Aşağı tökmə, yalnış yayım kimi təhlükəsiz deyil. Bilirsiniz ki, bir törəmə sinif obyekti hər zaman əsas sinif obyekti kimi qəbul edilə bilər. Lakin bunun tam əksi düzgün deyil. Məsələn, Menecer hər zaman Şəxsdir; Ancaq bir şəxs həmişə menecer deyil. Bu da bir Katib ola bilər.

Aşağı tökmə üçün açıq bir aktyor istifadə etməlisiniz:

//pointer to base class object
Employee* emp;
//object of derived class
Manager m1("Steve", "Kent", 3000, 0.2);
//implicit upcasting
emp = &m1;
//explicit downcasting from Employee to Manager
Manager* m2 = (Manager*)(emp);

Bu kod tərtib edir və heç bir problem olmadan işləyir, çünki emp menecer menecerinin bir obyektinə işarə edir.

Təməl sinifin bir obyektinə deyil, əsas sinifin bir obyektinə işarə edən bir əsas sinif göstəricisini aşağı salmağa çalışsaq nə olacaq? Bu kodu tərtib etməyə və işləməyə çalışın:

Employee e1("Peter", "Green", 1400);
//try to cast an employee to Manager
Manager* m3 = (Manager*)(&e1);
cout << m3->getComm() << endl;

e1 obyekti menecer sinfinin obyekti deyil. Komissiya haqqında heç bir məlumat yoxdur. Buna görə belə bir əməliyyat gözlənilməz nəticələr verə bilər.

Yenidən yaddaş düzümünə baxın:

C ++ tökmə və aşağı tökməPin

Həqiqətən, çıxarılan sinifin (Menecer) bir obyektini göstərməyən əsas sinif göstəricisini (İşçi) aşağı salmağa çalışdığınız zaman, əldə edilmiş sinif obyekti (sarı sahə) haqqında heç bir məlumatı olmayan yaddaşa giriş əldə edəcəksiniz. Aşağı düşmənin əsas təhlükəsi budur.

Bir növün başqa bir növə düzgün bir şəkildə çevrilə biləcəyini bilməyinizə kömək edə biləcək etibarlı bir aktyordan istifadə edə bilərsiniz. Bu məqsəd üçün dinamik bir aktyor istifadə edin.

Dinamik Oyuncu

dynamic_cast bir növü başqa bir növə etibarlı bir şəkildə çevirən bir operatordur. Bu vəziyyətdə söhbət mümkündür və təhlükəsizdir, çevrilən obyektin ünvanını qaytarır. Əks təqdirdə, nullptr qaytarır.

dynamic_cast aşağıdakı sintaksisə malikdir

	
dynamic_cast<new_type> (object)

Aşağı tökmə üçün dinamik bir tökmə istifadə etmək istəyirsinizsə, əsas sinif polimorf olmalıdır - ən azı bir virtual funksiyaya sahib olmalıdır. A əlavə edərək əsas sinif şəxsini dəyişdirin virtual funksiya:
virtual void foo() {}

İndi Employee sinif göstəricilərini əldə edilmiş sinif göstəricilərinə çevirmək üçün downcasting istifadə edə bilərsiniz.
Employee e1("Peter", "Green", 1400);
Manager* m3 = dynamic_cast<Manager*>(&e1);
if (m3)
	cout << m3->getComm() << endl;
else
	cout << "Can't  cast from Employee to Manager" << endl;

Bu vəziyyətdə, dinamik aktyor nullptr qaytarır. Buna görə bir xəbərdarlıq mesajı görəcəksiniz.

Bu yazıda, C ++ Yuxarıdan Yıxma və Aşağı Tökmə haqqında oxuduq. Növbəti məqalələrdə C ++ ilə bağlı daha çox mövzuya toxunacağıq.

arayış

Translate »
1