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.
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:SecureMessagesı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
Implsınıfı ve buna işaret eden birstd::unique_ptriç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 birstd::stringyö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.
- Özgün ileti için
SecureMessage.cpp: İç içeImplsınıfını tanımlayın ve tüm yöntemleri uygulayın.Implsı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_ptrtamImpltürüne ihtiyaç duyduğundan, varsayılan olarak tanımlanmış olsa bile yok ediciyi burada tanımlamayı unutmayın.main.cpp: İki girdi okuyun:- Bir ileti dizesi (boşluklar içerebilir)
- Bir şifreleme anahtarı (tamsayı)
Bir
SecureMessagenesnesi oluşturun, anahtarı ayarlayın ve sonuçları görüntüleyin:- Özgün iletinin ardından
Original:yazdırın - Şifrelenmiş iletinin ardından
Encrypted:yazdırın
Örneğin, hello world ve 3 girdileriyle:
Original: hello world
Encrypted: khoor zruogxyz abc ve 5 girdileriyle:
Original: xyz abc
Encrypted: cde fghBaş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;
}
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
1OOP Temelleri
Harici DosyalarC++ Build ve DerlemeBaşlık Dosyaları ve Kaynak DosyalarıAd Alanları ve KapsamC++'ta OOP'ye GirişSınıflar ve Nesneler'this' İşaretçisiMetotlar (Üye Fonksiyonlar)Öznitelikler (Veri Üyeleri)Ctor ve Dtor TemelleriÖzet - Basit Hesap Makinesi4Sınıf Özellikleri
Örnek ve Statik ÜyelerGetter ve Setter MetotlarıConst Üye FonksiyonlarMutable Anahtar KelimesiStatik Metotlar ve DeğişkenlerFriend Fonksiyonlar ve SınıflarÖzet - Banka Hesabı Yöneticisi7Kalıtım
Temel KalıtımKalıtım Erişim SeviyeleriCtor ve Dtor Çağrılma SırasıMetot Geçersiz KılmaSanal Fonksiyonlar ve VTableÇoklu KalıtımSanal KalıtımÖzet - Çalışan Hiyerarşisi10STL Genel Bakış
STL Genel Bakış ve FelsefesiSTL KonteynerleriİteratörlerSTL AlgoritmalarıFunctor'lar ve Lambda İfadeleriÖzet - Kelime Frekansı13Tasarım Kalıpları 1. Bölüm
Tasarım Kalıplarına GirişSingleton KalıbıFactory ve Abstract FactoryBuilder KalıbıObserver KalıbıStrategy Kalıbı2Bellek Yönetimi
Stack ve Heap Bellekİşaretçiler ve ReferanslarDinamik Bellek (new/delete)C++'ta Akıllı İşaretçilerC++'ta RAIIÖzet - Dinamik Dizi Yöneticisi5Kapsülleme
C++'da Erişim BelirleyicilerDerinlemesine Erişim BelirleyicilerBilgi GizlemeStruct vs Classİç İçe ve Dahili SınıflarÖzet - Öğrenci Kayıt Sistemi8Çok Biçimlilik
Derleme ve Çalışma Zamanı Çok BiçimliliğiFonksiyon Aşırı YüklemeSanal Fonksiyonlara Yeniden BakışSaf Sanal FonksiyonlarSoyut SınıflarC++'ta Arayüz TasarımıDynamic Casting ve RTTIÖzet - Şekil Hesaplayıcı3Yapıcılar ve Yıkıcılar
Varsayılan YapıcıParametreli YapıcıKopya YapıcıTaşıma YapıcısıYapıcı İlklendirme ListeleriTemsilci YapıcılarYıkıcılara Derinlemesine BakışÜç / Beş / Sıfır KuralıÖzet - String Sınıfı6Operatör Aşırı Yükleme
Operatör Aşırı Yüklemeye GirişAritmetik Operatör Aşırı YüklemeKarşılaştırma Operatörü Aşırı YüklemeStream OperatörleriAtama Operatörü Aşırı Yükleme[] ve () Operatör Aşırı YüklemeTip Dönüşüm OperatörleriÖzet - Matris Sınıfı9Şablonlar
Fonksiyon ŞablonlarıSınıf ŞablonlarıŞablon ÖzelleştirmeVariadic ŞablonlarSFINAE ve Type Traits TemelleriÖzet - Generic KonteynerKendi başına pratik yap: Online C++ derleyicisi