2013-05-28 35 views
6

C++ Tasarım Desenleri ve Türevleri Mark Joshi'nin fiyatlandırmasını ve onun kodunu C++ 11'de uygulayarak okuyorum. Sanal kopya kurucularından bahsettiği bölüm 4'e kadar her şey yolunda gitti. BuradaC++ 11 sanal kopya oluşturucu

PayOffDoubleDigital thePayOff(Low, Up); 
VanillaOption theOption(thePayOff, Expiry); 

sorun VanillaOptionthePayOff bir referans içerir olmasıdır. Bu durumda ve birisi thePayOff değiştirirse, theOption davranışı, istenmeden değiştirilebilir.

PayOff* PayOffCall::clone() const 
{ 
    return new PayOffCall(*this); 
} 

dönersek: Her kalıtsal sınıfında tanımlanan sonra

virtual PayOff* clone() const = 0; 

ve: o tavsiyede çözüm PayOffDoubleDigital 'ın taban sınıftaki sanal kopya kurucu oluşturmaktır, PayOff böylece theOption kendi kopyasını içeren Yeni, C++ 11'de uygunsuz olabilecek bir şey olarak beni yakaladı. Peki bu C++ 11 kullanarak işlemenin uygun yolu nedir?

+3

Sıfır kuralı: Uygun sahiplik semantiği ile bir tanıtıcı sınıf yapın ve her yerde kullanın. –

+0

Bazı ek araştırmam var gibi görünüyor. Teşekkürler Martinho. – BDig

+0

Daha önce yazdım: http://flamingdangerzone.com/cxx11/2012/08/15/rule-of-zero.html –

cevap

11

o tavsiyede çözüm tüm

Öncelikle clone() bir kopyası-yapıcı değildir [...] PayOffDoubleDigital taban sınıftaki sanal kopya kurucu oluşturmaktır.

X(X const&) 

Ve mayimzaya sahip: sınıfa X için bir kopyası yapıcı genellikle imzası hiçbir dönüş türü ile özel bir üye fonksiyonudur

X(X&) 

İşlevini clone() (sadece normal olduğunu virtual) işlevi ve onun özel anlamı sizin tarafından - kullanıcı - sizin nesnenizin klonlarını yaratan bir şey olarak tanınır, ancak derleyici tarafından değil, clone()'un ne yaptığı hakkında hiçbir fikre sahip değildir. Yeni ve Geri

uygunsuz olabilecek bir şey olarak beni yakaladı C++ new C++ 11'de deyimsel değildir kullanarak, doğru 11

. Aslında, C++ 11'de (hemen hemen)'u gerçekten düşük düzey bellek yönetimini kullanmıyorsanız (gerçekten gerçekten yapmanız gerekmedikçe bir şey yapmanız gerekir) - ve C++ 14'te kaldırabilirsiniz. neredeyse". Ne yazık ki, bu muhtemelen new'un gerekli olduğu istisnai bir durumdur.

Bunu söylüyorum çünkü bir unique_ptr döndürme işleminin burada yapılması uygun bir şey gibi geldiğine inanıyorum (seçenek nesnesi kendi PayOff nesnesini tutmalıdır ve bu seçenek nesnesinin canlı olduğu sürece hayatta kalmalıdır) ve C++ 11 hiçbir std::make_unique() işlevi yoktur (o C++ 14 de vardır):

std::unique_ptr<PayOff> PayOffCall::clone() const 
{ 
    return std::unique_ptr<PayOff>(new PayOffCall(*this)); 
} 

VanillaOption (veya temel sınıf) sahip tutun unique_ptr ham işaretçi olur yerine delete için clone() tarafından döndürülen PayOff nesnesine gerek yoktur. Sırasıyla, delete numaralı nesneye sahip olmamanın, kullanıcı tarafından sağlanan bir yok edici tanımlamaya gerek olmadığı ve Rule of Three, Rule of Five veya neye dikkat etmeyeceği anlamına gelir.

Ne zaman isterseniz, R. Martinho's Fernandes's advice öğelerini izleyin ve Rule of Zero'a gidin.

+0

İyi düşünülmüş yanıt için teşekkür ederim. Bu benim için ustalaşması zor C++ bir alandır. Yapabilseydim bunu işaretlerdim. Ama bu benim ilk sorum olduğum için gerekli itibara sahip değilim. Soruyu işaretlemek için daha fazla insana ihtiyacım var :) – BDig

+0

@BDig: Endişelenme, iyi sorular sormaya devam et ve yakında cevap vereceğim :) Memnuniyetle yardımcı olabilirim ve kitabınızla iyi şanslar –

0

Genellikle sahiplikle uğraşırken, en temiz çözüm bir akıllı işaretçi döndürmektir: her ikisi de istisna güvenliği (bellek sızıntısı riski) garanti eder ve nesnelerin kime ait olduğunu açıkça belirtir.

unique_ptr veya shared_ptr'u kullanmak isteyip istemediğiniz tamamen size bağlıdır.