C++ Örnekle Polimorfizm

⚡ Akıllı Özet

Polimorfizm C++ Tek bir üye fonksiyonunun, onu çağıran nesneye bağlı olarak farklı davranarak birçok biçim almasına olanak tanır. Kalıtıma dayanır ve derleme zamanında veya çalışma zamanında çözümlenen iki çeşidi bulunur.

  • 🔷 Tanım: Polimorfizm, "çoklu biçimler" anlamına gelir ve bir üye fonksiyonunun, onu çağıran nesneye bağlı olarak farklı davranmasına olanak tanır.
  • 🧭 İki tip: C++ Derleme zamanı (statik) polimorfizm ve çalışma zamanı (dinamik) polimorfizm sağlar.
  • 🧩 Derleme süresi: Fonksiyon aşırı yüklemesi ve operatör aşırı yüklemesi, derleme sırasında doğru fonksiyonun seçilmesini sağlar.
  • 🔁 Çalışma süresi: Fonksiyon geçersiz kılma ve sanal fonksiyonlar, program çalışırken çağrıyı çözümler.
  • ⚙️ Sanal fonksiyonlar: Temel sınıftaki `virtual` anahtar kelimesi, temel sınıf işaretçisi aracılığıyla geç bağlamayı mümkün kılar.
  • 🤖 Yapay zeka yardımı: GitHub Copilot ve benzeri yardımcı araçlar, kısa bir yorumdan aşırı yüklenmiş, geçersiz kılınmış ve sanal fonksiyonların iskeletini oluşturur.

C++ Polimorfizm

Polimorfizm Nedir? C++?

In C++Polimorfizm, bir üye fonksiyonunun onu çağıran/işleyen nesneye bağlı olarak farklı davranmasına neden olur. Polimorfizm, Yunanca'da "birçok biçime sahip olmak" anlamına gelen bir kelimedir. Bir hiyerarşiye sahip olduğunuzda ortaya çıkar. sınıflar Kalıtım yoluyla akraba.

Örneğin makeSound() fonksiyonuna sahip olduğumuzu varsayalım. Bir kedi bu işlevi çağırdığında miyav sesi çıkarır. Bir inek aynı işlevi çalıştırdığında, moow sesini çıkaracaktır.

Polimorfizm C++ makeSound örneği

Tek bir işlevimiz olmasına rağmen, farklı koşullar altında farklı davranır. Fonksiyonun birçok biçimi vardır; dolayısıyla polimorfizme ulaştık.

Temel fikir belirlendikten sonra, C++ Bu davranışı iki ayrı kategoriye ayırır.

Polimorfizm Türleri

C++ iki tür polimorfizmi destekler:

  • Derleme zamanı polimorfizmi ve
  • Çalışma zamanı polimorfizmi.

Polimorfizm türleri C++

Birinci kategori, program çalıştırılmadan önce her fonksiyon çağrısını çözümler.

Derleme Zamanı Polimorfizmi

Bağımsız değişkenlerin sayısını ve türünü eşleştirerek aşırı yüklenmiş işlevleri çağırırsınız. Bilgi derleme sırasında mevcuttur. Bu şu anlama gelir: C++ derleyici derleme zamanında doğru işlevi seçecektir.

Derleme zamanı polimorfizmi, işlevin aşırı yüklenmesi ve operatörün aşırı yüklenmesi yoluyla elde edilir.

İşlev Aşırı Yüklemesi

Fonksiyon aşırı yüklenmesi, benzer adlara ancak farklı argümanlara sahip birçok fonksiyonumuz olduğunda meydana gelir. Argümanlar sayı veya tür açısından farklılık gösterebilir.

Örnek 1

#include <iostream> 
using namespace std;

void test(int i) {
	cout << " The int is " << i << endl;
}
void test(double  f) {
	cout << " The float is " << f << endl;
}
void test(char const *ch) {
	cout << " The char* is " << ch << endl;
}

int main() {
	test(5);
	test(5.5);
	test("five");
	return 0;
}

Çıktı:

C++ Fonksiyon aşırı yüklemesi Örnek 1 çıktısı

İşte kodun ekran görüntüsü:

C++ Fonksiyon aşırı yüklemesi Örnek 1 kodu

Code Açıklama:

  1. iostream başlık dosyasını kodumuza ekleyin. Fonksiyonlarını kullanabileceğiz.
  2. Kodumuza std ad alanını ekleyin. Sınıflarını çağırmadan kullanabileceğiz.
  3. i tamsayı parametresini alan test adında bir işlev oluşturun. {, işlev testi gövdesinin başlangıcını işaret eder.
  4. Yukarıdaki fonksiyon testi çağrılırsa/çağrılırsa yürütülecek ifade.
  5. Yukarıdaki fonksiyon testinin gövdesinin sonu.
  6. Float parametresi f'yi alan test adında bir işlev oluşturun. {, işlev testi gövdesinin başlangıcını işaret eder.
  7. Yukarıdaki fonksiyon testi çağrılırsa/çağrılırsa yürütülecek ifade.
  8. Yukarıdaki fonksiyon testinin gövdesinin sonu.
  9. Ch karakter parametresini alan test adında bir işlev oluşturun. {, işlev testi gövdesinin başlangıcını işaret eder.
  10. Yukarıdaki fonksiyon testi çağrılırsa/çağrılırsa yürütülecek ifade.
  11. Yukarıdaki fonksiyon testinin gövdesinin sonu.
  12. Main() işlevini çağırın. { işlevin gövdesinin başlangıcını belirtir.
  13. Fonksiyon testini çağırın ve argümanın değeri olarak ona 5'i iletin. Bu, bir tamsayı argümanını kabul eden test fonksiyonunu, yani ilk test fonksiyonunu çağırır.
  14. Fonksiyon testini çağırın ve argümanın değeri olarak ona 5.5'i iletin. Bu, kayan argümanı kabul eden test fonksiyonunu, yani ikinci test fonksiyonunu çağıracaktır.
  15. Fonksiyon testini çağırın ve ona argümanın değeri olarak beşi iletin. Bu, bir karakter argümanını kabul eden test fonksiyonunu, yani üçüncü test fonksiyonunu çağıracaktır.
  16. Program başarılı bir şekilde çalışıyorsa bir değer döndürmelidir.
  17. main() fonksiyonunun gövdesinin sonu.

Aynı ada sahip ancak farklı türde argümanlara sahip üç fonksiyonumuz var. Polimorfizme ulaştık.

OperaTor Aşırı Yükleniyor

In OperaTor Aşırı Yükleme, için yeni bir anlam tanımlıyoruz. C++ ŞebekeBu aynı zamanda operatörün çalışma şeklini de değiştirir. Örneğin, + operatörünü iki dizeyi birleştirmek için tanımlayabiliriz. Bunu sayısal değerleri toplamak için kullanılan toplama operatörü olarak biliyoruz. Tanımlamamızdan sonra, tamsayılar arasına yerleştirildiğinde, onları toplayacaktır. Dizeler arasına yerleştirildiğinde ise, onları birleştirecektir.

Örnek 2

#include<iostream> 
using namespace std;

class ComplexNum {
private:
	int real, over;
public:
	ComplexNum(int rl = 0, int ov = 0) {
		real = rl;   
		over = ov; 
	}

	ComplexNum operator + (ComplexNum const &obj) {
		ComplexNum result;
		result.real = real + obj.real;
		result.over = over + obj.over;
		return result;
	}
	void print() { 
		cout << real << " + i" << over << endl; 
	}
};
int main()
{
	ComplexNum c1(10, 2), c2(3, 7);
	ComplexNum c3 = c1+c2;
	c3.print();
}

Çıktı:

C++ Operatör aşırı yüklemesi Örnek 2 çıktısı

İşte kodun ekran görüntüsü:

C++ Operatör aşırı yüklemesi Örnek 2 kodu

C++ Operatör aşırı yüklemesi Örnek 2 sonucu

Code Açıklama:

  1. Fonksiyonlarını kullanabilmek için iostream başlık dosyasını programımıza ekleyiniz.
  2. Sınıflarını çağırmadan kullanabilmek için std ad alanını programımıza ekleyin.
  3. ComplexNum adında bir sınıf oluşturun. { işareti sınıf gövdesinin başlangıcını işaretler.
  4. Değişkenleri özel olarak işaretlemek için özel erişim değiştiricisini kullanın; bu, onlara yalnızca sınıf içinden erişilebileceği anlamına gelir.
  5. Gerçek ve üzeri olmak üzere iki tamsayı değişkeni tanımlayın.
  6. Yapıcı metodu genel (public) olarak işaretlemek için `public` erişim değiştiricisini kullanın; bu, yapıcı metodun sınıfın dışından bile erişilebilir olacağı anlamına gelir.
  7. Sınıf yapıcısını oluşturun ve değişkenleri başlatın.
  8. Gerçek değişkenin değerini başlat.
  9. Değişkenin değerini sıfırlayın.
  10. Yapıcı gövdesinin sonu.
  11. + operatörünün anlamını geçersiz kılmamız gerekiyor.
  12. ComplexNum türündeki result veri türünü oluşturun.
  13. Karmaşık sayılarla + operatörünü kullanın. Bu satır bir sayının gerçek kısmını başka bir sayının gerçek kısmına ekleyecektir.
  14. Karmaşık sayılarla + operatörünü kullanın. Bu satır bir sayının sanal kısmını başka bir sayının sanal kısmına ekleyecektir.
  15. Program başarılı bir şekilde yürütüldüğünde değişken sonucunun değerini döndürecektir.
  16. + operatörünün yeni anlamı yani aşırı yükleme tanımının sonu.
  17. print() yöntemini çağırın.
  18. Konsolda toplama işleminden sonra yeni karmaşık sayıyı yazdır.
  19. print() fonksiyonunun gövdesinin sonu.
  20. ComplexNum sınıfının gövdesinin sonu.
  21. Main() işlevini çağırın.
  22. Eklenecek hem gerçek hem de karmaşık kısımların değerlerini geçirin. c1'in ilk kısmı c2'nin ilk kısmına eklenecektir, yani 10+3. c1'in ikinci kısmı c'nin ikinci kısmına eklenecektir, yani 2+7.
  23. Aşırı yüklenmiş + operatörünü kullanarak ve sonucu c3 değişkeninde saklayarak bir işlem gerçekleştirin.
  24. c3 değişkeninin değerini konsola yazdırın.
  25. main() işlevinin gövdesinin sonu.

Derleme zamanı polimorfizminin erken karar verdiği durumlarda, ikinci kategori seçimi yürütme anına erteler.

Çalışma Zamanı Polimorfizmi

Bu, bir nesnenin yöntemi derleme zamanı yerine çalışma zamanı sırasında çağrıldığında/çağrıldığında meydana gelir. Çalışma zamanı polimorfizmi, işlevin geçersiz kılınması yoluyla elde edilir. Çağrılacak/çağırılacak işlev çalışma zamanı sırasında oluşturulur.

İşlev Geçersiz Kılma

Fonksiyon geçersiz kılma, temel sınıfın bir fonksiyonuna türetilmiş bir sınıfta yeni bir tanım verildiğinde meydana gelir. O zaman temel fonksiyonun geçersiz kılındığını söyleyebiliriz.

Örneğin:

#include <iostream>
using namespace std;
class Mammal {

public:
	void eat() {

		cout << "Mammals eat...";
	}

};

class Cow: public Mammal {

public:
	void eat() {

		cout << "Cows eat grass...";
	}
};
int main(void) {

	Cow c = Cow();

	c.eat();

	return 0;

}

Çıktı:

C++ fonksiyon çıktısını geçersiz kılıyor

İşte kodun ekran görüntüsü:

C++ fonksiyon geçersiz kılma kodu

Code Açıklama:

  1. İşlevlerini kullanmak için iostream başlık dosyasını programımıza aktarın.
  2. Sınıflarını çağırmadan kullanabilmek için std ad alanını programımıza ekleyin.
  3. Memeli adında bir sınıf oluşturun. {, sınıf gövdesinin başlangıcını işaret eder.
  4. Oluşturmak üzere olduğumuz işlevi herkese açık olarak ayarlamak için genel erişim değiştiricisini kullanın. Bu sınıfın dışından erişilebilir olacaktır.
  5. Eat adında genel bir işlev oluşturun. {, işlev gövdesinin başlangıcını işaret eder.
  6. Eat() işlevi çağrıldığında cout işlevine eklenen ifadeyi yazdırın.
  7. Eat() fonksiyonunun gövdesinin sonu.
  8. Memeli sınıfının gövdesinin sonu.
  9. Memeli sınıfını miras alan Cow adında bir sınıf oluşturun. Cow türetilmiş sınıftır, Mammal ise temel sınıftır. { bu sınıfın başlangıcını işaret eder.
  10. Oluşturmak üzere olduğumuz işlevi herkese açık olarak işaretlemek için genel erişim değiştiricisini kullanın. Bu sınıfın dışından erişilebilir olacaktır.
  11. Temel sınıfta tanımlanan eat() fonksiyonunu geçersiz kılın. {, işlev gövdesinin başlangıcını işaret eder.
  12. Bu işlev çağrıldığında konsolda yazdırılacak ifade.
  13. Eat() fonksiyonunun gövdesinin sonu.
  14. İnek sınıfının gövdesinin sonu.
  15. Main() işlevini çağırın. {, bu fonksiyonun gövdesinin başlangıcını işaret eder.
  16. Cow sınıfının bir örneğini oluşturun ve ona c adını verin.
  17. Cow sınıfında tanımlanan eat() işlevini çağırın.
  18. Program başarılı bir şekilde tamamlandığında bir değer döndürmelidir.
  19. Main() fonksiyonunun sonu.

C++ Sanal İşlev

Sanal işlev, çalışma zamanı polimorfizmini uygulamanın başka bir yoludur. C++. Temel sınıfta tanımlanan ve türetilmiş sınıfta yeniden tanımlanan özel bir fonksiyondur. Sanal bir işlev bildirmek için sanal anahtar kelimeyi kullanmalısınız. Anahtar kelime, temel sınıftaki işlevin bildiriminden önce gelmelidir.

Bir sanal işlev sınıfı miras alınırsa sanal sınıf, sanal işlevi kendi ihtiyaçlarına uyacak şekilde yeniden tanımlar. Örneğin:

#include <iostream>  
using namespace std;
class ClassA {
		public:
		virtual void show() {
			cout << "The show() function in base class invoked..." << endl;
		}
	};
	class ClassB :public ClassA {
	public:
		void show() 	{
			cout << "The show() function in derived class invoked...";
		}
	};
	int main() {
		ClassA* a;   
		ClassB b;
		a = &b;
		a->show();      
	}

Çıktı:

C++ sanal fonksiyon çıktısı

İşte kodun ekran görüntüsü:

C++ sanal fonksiyon kodu

Code Açıklama:

  1. İşlevlerini kullanmak için iostream başlık dosyasını koda ekleyin.
  2. Sınıflarını çağırmadan kullanmak için std ad alanını kodumuza ekleyin.
  3. ClassA adında bir sınıf oluşturun.
  4. Bir sınıf üyesini genel olarak erişilebilir olarak işaretlemek için genel erişim değiştiricisini kullanın.
  5. show() adında bir sanal işlev oluşturun. Kamuya açık bir etkinlik olacak.
  6. show() çağrıldığında yazdırılacak metin çağrılır. Sonu bir C++ bitiş çizgisi anlamına gelen anahtar kelime. Fare imlecini bir sonraki satıra taşır.
  7. Show() sanal fonksiyonunun gövdesinin sonu.
  8. ClassA sınıfının gövdesinin sonu.
  9. ClassA sınıfını miras alan ClassB adında yeni bir sınıf oluşturma. ClassA temel sınıf olurken ClassB türetilmiş sınıf olur.
  10. Bir sınıf üyesini genel olarak erişilebilir olarak işaretlemek için genel erişim değiştiricisini kullanın.
  11. Temel sınıfta türetilen show() sanal işlevini yeniden tanımlayın.
  12. Türetilmiş sınıfta tanımlanan show() işlevi çağrıldığında konsolda yazdırılacak metin.
  13. show() fonksiyonunun gövdesinin sonu.
  14. Türetilmiş sınıfın gövdesinin sonu, ClassB.
  15. Main() işlevini çağırın. Program mantığı kendi bünyesinde eklenmelidir.
  16. a adında bir işaretçi değişkeni oluşturun. ClassA isimli sınıfa işaret eder.
  17. ClassB adlı sınıfın bir örneğini oluşturun. Örneğe b adı verilir.
  18. b adresindeki değer depolarını a değişkenine atayın.
  19. Türetilmiş sınıfta tanımlanan show() işlevini çağırın. Geç bağlama uygulandı.
  20. Main() işlevinin gövdesinin sonu.

Her iki mekanizma da ele alındığında, aşağıdaki tabloda bunlar yan yana karşılaştırılmıştır.

Derleme Zamanı Polimorfizmi Vs. Çalışma Zamanı Polimorfizmi

İşte ikisi arasındaki temel farklar:

Derleme zamanı polimorfizmi Çalışma zamanı polimorfizmi
Buna erken bağlanma veya statik polimorfizm de denir. Geç/dinamik bağlanma veya dinamik polimorfizm olarak da adlandırılır.
Yöntem derleme sırasında çağrılır/çağırılır Yöntem çalışma zamanı sırasında çağrılır/çağırılır
İşlev aşırı yüklemesi ve operatör aşırı yüklemesi yoluyla uygulanır Yöntem geçersiz kılma ve sanal işlevler aracılığıyla uygulanır
Örnek, yöntemin aşırı yüklenmesi. Birçok yöntemin benzer adları olabilir ancak farklı sayı veya türde argümanları olabilir. Örnek, yöntem geçersiz kılma. Birçok yöntemin benzer adı ve aynı prototipi olabilir.
Metot keşfi derleme zamanında yapıldığı için daha hızlı yürütme sağlanır. Metot keşfi çalışma zamanında yapıldığı için yürütme daha yavaştır.
Less Derleme süresi boyunca her şey bilindiği için problem çözmede esneklik sağlanır. Yöntemler çalışma zamanında keşfedildiğinden karmaşık problemlerin çözümünde büyük esneklik sağlanır.

SSS

Aşırı yükleme, aynı ada sahip ancak farklı parametrelere sahip birden fazla fonksiyon tanımlar ve bu fonksiyonlar kalıtım olmadan derleme zamanında çözümlenir. Geçersiz kılma ise, türetilmiş bir sınıfta aynı imzaya sahip, kalıtım yoluyla edinilmiş bir temel sınıf fonksiyonunu yeniden tanımlar ve bu fonksiyon sanal olarak bildirildiğinde çalışma zamanında çözümlenir.

Saf sanal fonksiyon, `= 0` ile tanımlanır ve temel sınıfta gövdesi yoktur. Bu fonksiyonu içeren herhangi bir sınıf, mutlak sanal fonksiyon haline gelir.tracDoğrudan örneklendirilemeyen ve türetilmiş sınıfların kendi uygulamalarını sağlamasını zorunlu kılan bir sınıf.

Bir sınıf sanal fonksiyonlar bildirdiğinde, derleyici fonksiyon işaretçilerinden oluşan bir sanal tablo (vtable) oluşturur. Her nesne, kendi sınıf vtable'ına gizli bir işaretçi saklar; böylece temel sınıf işaretçisi, çalışma zamanında geç bağlama yoluyla doğru geçersiz kılınmış fonksiyonu çağırır.

Evet. Şablonlar, bir fonksiyonun veya sınıfın birçok veri türü üzerinde çalışmasına olanak tanır ve derleyici, derleme sırasında türe özgü kod üretir. Bu genel programlama, fonksiyon aşırı yüklemesi ve operatör aşırı yüklemesini tamamlayan bir statik polimorfizm biçimidir.

Türetilmiş bir nesneyi temel sınıf işaretçisi aracılığıyla sildiğinizde, yalnızca sanal bir yıkıcı, türetilmiş yıkıcının da çalışmasını garanti eder. Sanal yıkıcı olmadan, temizleme işlemi eksik kalır ve bellek sızıntılarına neden olur. Temel yıkıcıyı sanal olarak bildirmek, yıkımın polimorfik davranmasını sağlar.

Polimorfizm, tek bir arayüzün birçok nesne türünü işlemesine olanak tanıyarak tekrarlanan kodu azaltır ve bakımı kolaylaştırır. Yeni türetilmiş sınıfların mevcut kodu değiştirmeden entegre edilebildiği esnek ve genişletilebilir tasarımları destekler ve temel sınıf işaretçileri ve referansları üzerine kurulu güçlü kalıpları mümkün kılar.

Evet. Yapay zekâ kodlama asistanları kısa bir yorumu aşırı yüklenmiş fonksiyonlara, sanal temel sınıflara ve türetilmiş geçersiz kılmalara dönüştürür. Tekrarlayan şablon kodlarını hızlıca hallederler, ancak oluşturulan kodu derlemeden önce sanal anahtar kelimeleri, fonksiyon imzalarını ve yıkıcı güvenliğini yine de doğrulamanız gerekir.

Evet. GitHub Yardımcı Pilotu Yazarken sanal fonksiyon bildirimleri, türetilmiş sınıf geçersiz kılmaları ve operatör aşırı yüklemeleri önerir. Kalıtım hiyerarşileri için tekrarlayan kod yazımını hızlandırır, ancak derlemeden önce `virtual` anahtar kelimesini, eşleşen imzaları ve doğru geç bağlama davranışını doğrulamanız gerekir.

Bu yazıyı şu şekilde özetleyin: