2013-07-08 11 views
5

Varsayılan bir kurucu veya kopya yapımcısı bulunmayan, elmas şeklinde bir sınıf hiyerarşisi var. Ben iki kurucular bir "hareket" bir ve bir nesneye bir lvalue başvurusu alır başka: elmas biçimli hiyerarşi kullanmayan yanındaElmas şeklindeki bir miras için bir hareket yapıcısı nasıl uygulanır?

struct base { 
    base(base&&) = default; 
    base(member_type&& m): member_(std::move(m)) {} 
    member_type member_; 
}; 

struct virt_1: virtual base { 
    virt_1(virt_1&& rhs): base(std::move(rhs)) {} 
    virt_1(member_type&& m): base(std::move(m)) {} 
}; 

struct virt_2: virtual base { 
    virt_2(virt_2&& rhs): base(std::move(rhs)) {} 
    virt_2(member_type&& m): base(std::move(m)) {} 
}; 

struct concrete: virt_1, virt_2 { 
    concrete(concrete&& rhs) // ??? 
}; 

, somut sınıf için hamle yapıcı uygulamak mümkündür ?

Teşekkürler!

+1

Sesler bana çok eğilimli geliyor. Sanal tabanın kurucusu, en türetilmiş sınıftan çağrılır ve bir hareket ettiriciyi aramadığı için hiçbir sebep olmamalıdır. Ama herhangi bir başka türetme, ve birisinin onu unutacağı ya da yanlış yaptığı iyi bir şans var. Genel bir kural olarak, sanal temel sınıfları bu tür sorunları önlemek için veri içermemeli veya en azından varsayılan kurucudan başka kurucular içermemelidir. –

+0

@JamesKanze "base" in veri içermemesi veya en azından varsayılan bir kurucu içermesi gerektiğinin farkındayım, ancak bağlamımda durum böyle olamaz. Ancak, bir kişi, daha fazla türetirken sanal taban yapıcısını çağırmayı unutursa, derleyicinin şikayet edeceği ihtimali var mıdır? base' hiçbir varsayılan kurucu vardır, bu yüzden en türetilmiş tip ** zorunluluk ** Ben elmas şekli mümkündür "kırılma" itiraf etmeliyim açıkça – piwi

+0

@piwi, hayır, hiç şans yok ama çok fazla iş gerektirecek. İnsanlar daha önce anlamadığım/anlamadığı başlatıcılara yapılan çağrıların "faydasızlığı" ile ilgili olarak işaret ettikleri gibi, bu hiyerarşiden kaçınmanın bu çözümünü umuyoruz: -/Teşekkürler –

cevap

8

Derleyiciden uygulamayı sağlamasını istemekte sorun nedir? Çok varsayılan olarak

concrete(concrete&&) = default; 

Ben virt_1 ve virt_2 hareket kurucular tanımlamak istiyorum. Gerçekten yazarak gibi size

concrete(concrete&& rhs) 
: base(std::move(rhs)), virt_1(std::move(rhs)), virt_2(std::move(rhs)) 
{ } 

Veya eğer: Eğer gerçekten istiyorsa

Sen bunu yazabiliriz

concrete(concrete&& rhs) 
    : base(static_cast<base&&>(rhs)), 
     virt_1(static_cast<virt_1&&>(rhs)), 
     virt_2(static_cast<virt_2&&>(rhs)) 
    { } 

virt_1 ve virt_2 üsleri için initializers, yararsız çünkü onlar sadece base yapıcısını arayın ve concrete bunu çağırdığında bunu yapmayacağınız bir sanal temel olarak, ancak yapıcı seçimlerinizden dolayı bunları varsayılan olarak yapılandıramazsınız ve bunları bir rvalue, onunla hiçbir şey yapmasalar bile.

+1

Soru: Bu tehlikeli olmaz mıydı? Aynı nesneden birden çok kez hareket ediyor gibi görünüyor ... –

+0

Sorunumun hem beton sınıfının yapıcıları hem de yalancı olduğunu düşünüyorum; Ben varsayılan hareket kurucu – piwi

+1

@AndyProwl ile hayır, umuyoruz ekledim son paragraf bakın. 'Base' yapıcısı sadece bir kez çağrılır (en türetilmiş tipte kurucu tarafından), böylece diğer tüm kurucular gerçekte kendi rıhtım parametresiyle bir şey yapmazlar. Sadece bir hareket olacak (“std :: move” kelimesinin aslında bir şey taşımadığını hatırlayın, bir hareket sadece bir şey bir ritim parametresini kabul ettiğinde ve ondan hareket etmeyi seçtiğinde gerçekleşir.) –

1

Elbette. Hiyerarşide bir yerde virtual tabanına sahip herhangi bir kurucu, bu tabanın başlatılmasından sorumludur. Temel olarak, hiyerarşideki virtual tabanının altındaki herhangi bir sınıf, tabanı ilklendirmek için izni devralır.

Bu durumda, varsayılan taşıma kurucusu doğru olanı yapmalıdır. Neler olup bittiğini açıklamak için concrete : private virtual base'u belirtmenizi de tavsiye ederim.

Here

bir çalışma demo.

+0

Ayrıca hareket ataması operatörünü de test edebilir. –

+1

Sınıfın doğrudan temelden miras kalması gerekmiyor. Ancak, herhangi bir sanal üsün kurucularını, onlardan miras kalmasalar bile çağırmaktan sorumludur. –

+0

@JamesKanze Oh, dolaylı bir temel için bir mem-başlatıcısına sahip olmanın bir sözdizimi hatası olduğunu düşündüm. Değil. Yine de, eğer yanılıyorsam düzeltin, ancak fark sadece sözdizimi/stili. Bazdan da miras almanın hiçbir farkı olmaz ve “sanal” olmaksızın tabandan miras almanın yasadışı olması gerekir. – Potatoswatter

İlgili konular