Diyelim ki sınıfı Foobar
kullanan (bağlı) bir sınıfım var Widget
. İyi günlerde, polimorfik davranış gerekiyorsa Widget
wolud bir alan olarak Foobar
veya belki de akıllı bir işaretçi olarak ilan edilir ve yapıcıda başlatılır:
class Foobar {
Widget widget;
public:
Foobar() : widget(blah blah blah) {}
// or
std::unique_ptr<Widget> widget;
public:
Foobar() : widget(std::make_unique<Widget>(blah blah blah)) {}
(…)
};
Ve hepimiz hazır olurduk. Ne yazık ki, bugün Java çocuklar gördükten sonra bize ve çiftler Foobar
ve Widget
birlikte haklı olarak gülecekler . Çözüm basit görünüyor: Bağımlılıkların inşasını Foobar
sınıftan çıkarmak için Bağımlılık Enjeksiyonu uygulayın . Ama sonra, C ++ bizi bağımlılıkların sahibi olmayı düşünmeye zorlar. Üç çözüm akla geliyor:
Benzersiz işaretçi
class Foobar {
std::unique_ptr<Widget> widget;
public:
Foobar(std::unique_ptr<Widget> &&w) : widget(w) {}
(…)
}
Foobar
sadece mülkiyetin Widget
kendisine geçildiğini iddia ediyor . Bunun aşağıdaki avantajları vardır:
- Performans üzerindeki etkisi ihmal edilebilir düzeydedir.
Foobar
Kontroller ömür boyu güvenliWidget
olduğundan,Widget
aniden kaybolmadığından emin olur .Widget
Sızıntı yapmayacak ve artık ihtiyaç duyulmadığında düzgün şekilde tahrip edilecek güvenlidir .
Ancak, bunun bir maliyeti vardır:
Widget
Örneklerin nasıl kullanılabileceği konusunda kısıtlamalar getirir, örneğin yığın tahsisWidgets
edilemez,Widget
paylaşılamaz.
Paylaşılan işaretçi
class Foobar {
std::shared_ptr<Widget> widget;
public:
Foobar(const std::shared_ptr<Widget> &w) : widget(w) {}
(…)
}
Bu muhtemelen Java ve çöp toplanan diğer dillere en yakın eşdeğerdir. Avantajları:
- Bağımlılık paylaşımına izin verdiği için daha evrensel.
unique_ptr
Çözeltinin güvenliğini (madde 2 ve 3) korur .
Dezavantajları:
- Paylaşım olmadığında kaynakları israf eder.
- Yine de yığın ayırma gerektirir ve yığınla ayrılmış nesneleri devre dışı bırakır.
Düz ol 'gözlem işaretçisi
class Foobar {
Widget *widget;
public:
Foobar(Widget *w) : widget(w) {}
(…)
}
Ham işaretçiyi sınıfın içine yerleştirin ve sahip olma yükünü bir başkasına kaydırın. Artıları:
- Olabildiğince basit.
- Universal, sadece herhangi birini kabul eder
Widget
.
Eksileri:
- Artık güvenli değil.
- Her ikisinin
Foobar
ve sahipliğinden sorumlu olan başka bir varlık tanıtırWidget
.
Bazı çılgın şablon meta programlaması
Düşünebileceğim tek avantaj, yazılımım derlenirken zaman bulamadığım tüm kitapları okuyabileceğim;)
Üçüncü çözüme yaslanıyorum, en evrensel olduğu gibi, bir şey Foobars
yine de yönetmek zorunda , bu yüzden yönetmek Widgets
basit bir değişiklik. Ancak, ham işaretçiler kullanmak beni rahatsız ediyor, diğer taraftan akıllı işaretçi çözümü bana yanlış geliyor, çünkü bağımlılık tüketicisini bu bağımlılığın nasıl yaratıldığını kısıtlıyorlar.
Bir şey mi kaçırıyorum? Yoksa sadece C ++ bağımlılık enjeksiyon önemsiz değil mi? Sınıf bağımlılıklarına mı sahip olmalı yoksa sadece gözlemlemeli mi?
Foobar
tek sahibi olduğunu nasıl bilebilirim ? Eski durumda basit. Ancak DI ile ilgili sorun, gördüğüm gibi, sınıfı bağımlılıklarının inşasından ayırdığı için, aynı zamanda bu bağımlılıkların sahipliğinden de ayrıştırmasıdır (sahiplik inşaata bağlı olduğu için). Java gibi çöp toplanmış ortamlarda bu bir sorun değildir. C ++ 'da, bu.
std::unique_ptr
gidilecek yoldur.std::move()
Bir kaynağın sahipliğini üst kapsamdan sınıfa aktarmak için kullanabilirsiniz .