ProgramlamaOrta Düzey C++ Geliştiricisi

C++'de yerleşik (primitive) ve kullanıcı tanımlı (user-defined) tipler nedir, nasıl farklılık gösterirler ve karmaşık programların tasarımında neden önemlidir?

Hintsage yapay zeka asistanı ile mülakatları geçin

Cevap.

Soru tarihçesi:

C++, sayı, sembol, dizi gibi az sayıda yerleşik tip sunan C dilinin üzerine inşa edilmiştir. Dilin gelişmesiyle birlikte yapı, sınıf, enumerasyon gibi kavramlar kullanıcı tanımlı tipler haline gelmiştir.

Sorun:

Bir programdaki veri türü, değişkenin ne kadar bellek kaplayacağını, nasıl başlatılacağını, kopyalanacağını, yok edileceğini, karşılaştırılacağını tanımlar. Yerleşik tipler standart bir davranışa sahiptir; kullanıcı tanımlı türlerin ise tüm yönlerinin belirtilmesi gerekir. Kullanıcı tanımlı tiplerin yönetimindeki hatalar, çökme, bellek sızıntıları, nesnelerin haksız karşılaştırılması gibi sorunlara yol açabilir.

Çözüm:

Yerleşik tipler: int, float, double, char, bool ve diğer "primitifler". Kullanıcı tanımlı tipler: sizin oluşturduğunuz yapı, sınıf, birleşim vb. karmaşık görevler için, kopyalama, karşılaştırma, kaynak yönetimi gibi doğru bir semantik ile kullanıcı tanımlı tiplerin entegre edilmesi gerekir.

Kod örneği:

// Yerleşik tip int x = 5; // Kullanıcı tanımlı tip struct Point { double x, y; }; Point a = {1.0, 2.0}; // Kaynak içeren sınıf class MyFile { public: MyFile(const std::string& fn) : f(fopen(fn.c_str(), "r")) {} ~MyFile() { if (f) fclose(f); } private: FILE* f; };

Ana özellikler:

  • Yerleşik tipler: hızlı, kopyalama basit, bilinen boyut ve davranış.
  • Kullanıcı tanımlı: karmaşık varlıkları tanımlamak için gereklidir, kaynaklarla yönetim yapabilir, yapıcı ve yıkıcıların uygulanmasını gerektirir.
  • İşlemlerin semantiği üzerindeki kontrol (+, =, ==), dönüştürme ve diğer davranış yönleri.

Hileli sorular.

Kullanıcı tanımlı tipler tamamen yerleşik bir şekilde (örneğin, == ile karşılaştırma gibi) davranabilir mi?

Hayır, == ile karşılaştırma varsayılan olarak sadece C++20'den itibaren defaulted operator== ile çalışır, öncesinde açık bir tanım gerekiyordu.

Eğer sınıf yalnızca ham bir işaretçi (int, FILE, vb.) tutuyorsa, kopyalama yapıcı ve yıkıcı uygulamamak olur mu?**

Hayır, bu durumda varsayılan kopyalama "yüzeysel" olur, bu da bellek veya kaynak sızıntılarına veya çifte serbest bırakmalara yol açar. "Beş Kuralı" uygulamak gerekir.

Yapının varsayılan değeri sıfırla başlatılacak mı (Point p;)?

Hayır, yerel bir yapı başlangıç değeri olmadan tanımlanabilir, bellek içeriği rastgeledir. Açık bir başlatma kullanın.

Tipik hatalar ve anti-paternerler

  • Kullanıcı tanımlı tiplerin açık başlatılmasını ihmal etmek.
  • Dinamik bellek için sınıflarda yıkıcı ve kopyalama yapıcısını uygulamamak.
  • Yerleşik tiplerle kaynakları yönetmeye çalışmak (örneğin, ham işaretçiler).

Gerçek hayattan bir örnek

Olumsuz durum:

Bir dosya sarmalayıcı sınıf yıkıcıyı uygulamamıştır. Program, dosya tanıtıcılarını kapatmadan binlerce dosya işlemeye başladığında çalışıyordu.

Artılar: daha az kod, sade görünüm Eksiler: kaynak sızıntıları, dengesiz davranış

Olumlu durum:

Sınıf RAII uyguluyor — dosya yapıcıda açılır, yıkıcıda kapanır, kopyalamaya izin verilmez.

Artılar: güvenilirlik, emniyet, temiz arayüz Eksiler: "beş kuralı" hatırlama gerekliliği ve daha fazla kod yazma gerekiyor.