Menu
Coddy logo textTech

Pimpl İdiyomu

Coddy'nin C++ Journey'sinin Nesne Yönelimli Programlama bölümünün bir parçası. Ders 78 / 104.

Pimpl deyimi (Uygulamaya İşaretçi), bir sınıfın uygulama ayrıntılarını ayrı, ileriye dönük bildirimi yapılmış bir sınıfa taşıyarak gizleyen bir tekniktir. Bu, derleme bağımlılıklarını azaltır ve özel üyelerin başlık dosyasından gerçekten gizli kalmasını sağlar.

Temel fikir basittir: özel üyeleri doğrudan sınıfınızda bildirmek yerine, yalnızca kaynak dosyasında tanımlanan bir uygulama sınıfına işaretçi bildirirsiniz:

// Widget.h
#include <memory>

class Widget {
public:
    Widget();
    ~Widget();
    void doSomething();
    
private:
    class Impl;  // İleri bildirim
    std::unique_ptr<Impl> pImpl;
};
// Widget.cpp
#include "Widget.h"
#include <iostream>

class Widget::Impl {
public:
    int data = 42;
    void process() { std::cout << "Processing: " << data << "\n"; }
};

Widget::Widget() : pImpl(std::make_unique<Impl>()) {}
Widget::~Widget() = default;

void Widget::doSomething() { pImpl->process(); }

Temel avantajlar derleme güvenlik duvarı ve ikili uyumluluk özellikleridir. Impl sınıfını değiştirdiğinizde, header içeren her dosyanın değil, yalnızca kaynak dosyanın yeniden derlenmesi gerekir. Bu, büyük projelerde derleme sürelerini önemli ölçüde hızlandırır.

Yıkıcının kaynak dosyada tanımlanması gerektiğini (varsayılan olsa bile) unutmayın; çünkü unique_ptr, onu silebilmek için Impl türünün tamamlanmış hâline ihtiyaç duyar. Bu, Pimpl’ı ilk kez kullanırken sık karşılaşılan bir tuzaktır.

challenge icon

Görev

Kolay

Şifreleme uygulamasının ayrıntılarını başlık dosyasından gizlemek için Pimpl deyimini kullanarak güvenli bir ileti işleyicisi oluşturalım. Bu, Pimpl'ın bir derleme güvenlik duvarını nasıl oluşturduğunu gösterir: başlık dosyanızı dahil eden hiç kimse ileti işleme sürecinizin iç işleyişini göremez.

Kodunuzu üç dosyaya ayıracaksınız:

  • SecureMessage.h: SecureMessage sınıfınızın herkese açık arayüzünü tanımlayın.

    Sınıfınızın önceden bildirimi yapılmış bir Impl sınıfı ve buna işaret eden bir std::unique_ptr içermesi gerekir. Herkese açık arayüz şunları içermelidir:

    • Özgün ileti için const std::string& alan bir oluşturucu
    • Bir yok edici (.cpp dosyasında bildirilmeli ve tanımlanmalıdır)
    • Şifreleme anahtarını ayarlamak için bir setKey(int key) yöntemi
    • Şifrelenmiş iletiyi getEncrypted() olarak döndüren bir std::string yöntemi
    • Özgün iletiyi döndüren bir getOriginal() yöntemi

    Başlık dosyası yalnızca herkese açık arayüzü göstermelidir: şifrelemenin nasıl çalıştığıyla ilgili hiçbir uygulama ayrıntısı burada görünür olmamalıdır.

  • SecureMessage.cpp: İç içe Impl sınıfını tanımlayın ve tüm yöntemleri uygulayın.

    Impl sınıfınız özgün iletiyi ve şifreleme anahtarını (varsayılan olarak 0) saklamalı ve gerçek şifreleme mantığını yönetmelidir. Şifreleme için basit bir Sezar şifresi kullanın: her karakteri anahtar değerine göre kaydırın. Örneğin, anahtar 3 olduğunda 'a', 'd' olur ve 'z', 'c' olacak şekilde başa döner.

    Şifreleme yalnızca küçük harfleri (a-z) etkilemeli, diğer tüm karakterleri değiştirmeden bırakmalıdır. unique_ptr tam Impl türüne ihtiyaç duyduğundan, varsayılan olarak tanımlanmış olsa bile yok ediciyi burada tanımlamayı unutmayın.

  • main.cpp: İki girdi okuyun:
    1. Bir ileti dizesi (boşluklar içerebilir)
    2. Bir şifreleme anahtarı (tamsayı)

    Bir SecureMessage nesnesi oluşturun, anahtarı ayarlayın ve sonuçları görüntüleyin:

    1. Özgün iletinin ardından Original: yazdırın
    2. Şifrelenmiş iletinin ardından Encrypted: yazdırın

Örneğin, hello world ve 3 girdileriyle:

Original: hello world
Encrypted: khoor zruog

xyz abc ve 5 girdileriyle:

Original: xyz abc
Encrypted: cde fgh

Başlık dosyasının Sezar şifresinin uygulanışı hakkında hiçbir şey açığa çıkarmadığına dikkat edin: Pimpl'ın gücü budur. Daha sonra farklı bir şifreleme algoritmasına geçerseniz, başlık dosyasını içeren hiçbir dosyanın değil, yalnızca SecureMessage.cpp dosyasının yeniden derlenmesi gerekir.

Kendin dene

#include <iostream>
#include <string>
#include "SecureMessage.h"

int main() {
    // Mesajı oku (boşluk içerebilir)
    std::string message;
    std::getline(std::cin, message);
    
    // Şifreleme anahtarını oku
    int key;
    std::cin >> key;
    
    // TODO: Mesaj ile bir SecureMessage nesnesi oluştur
    
    // TODO: Şifreleme anahtarını ayarla
    
    // TODO: "Original: " yazdır ardından orijinal mesajı
    
    // TODO: "Encrypted: " yazdır ardından şifrelenmiş mesajı
    
    return 0;
}
quiz iconKendini test et

Bu ders kısa bir quiz içerir. Soruları yanıtlamak ve ilerlemeni kaydetmek için derse başla.

Nesne Yönelimli Programlama bölümündeki tüm dersler

Kendi başına pratik yap: Online C++ derleyicisi