2015-10-05 19 views
8

C++ 11'in yapıcı devralma özelliğini kullanmaya çalışıyorum. (Ben nereden hatırlamıyorum bir yerden kopyalanmış) Aşağıdaki pasajı tamamen iyi çalışır:Kopyalama kurucusu silme, devralınan yapıcılar

comment damgasını hat eklenene kadar olduğu
#include <iostream> 

struct Base { 
    Base() : Base(0) {} 
    Base(int a) : Base(a, 0) {} 
    Base(int a, double b) { std::cout << "Base(" << a << "," << b << ")" << std::endl; } 
}; 

struct Derived : Base { 
    using Base::Base; 
    Derived(const Derived& that) = delete; // This line is the culprit 
}; 

int main(int argc, char* argv[]) { 
    Derived d1; 
    Derived d2(42); 
    Derived d3(42, 3.14); 
} 

; Sonra çünkü her şey gevşek tatili: Ayrıca her nasılsa ulaşılmaz Base varsayılan yapıcısı yapılan kopya kurucu silme sanki

> g++ -std=c++11 -o test test.cpp 
test.cpp: In function ‘int main(int, char**)’: 
test.cpp:18:11: error: no matching function for call to ‘Derived::Derived()’ 
    Derived d1; 
     ^
test.cpp:18:11: note: candidates are: 
test.cpp:13:16: note: Derived::Derived(int) 
    using Base::Base; 
       ^
test.cpp:13:16: note: candidate expects 1 argument, 0 provided 
test.cpp:13:16: note: Derived::Derived(int, double) 
test.cpp:13:16: note: candidate expects 2 arguments, 0 provided 

görünüyor. Sorunun giderilmesi faydalı bir şey getirmedi; SO this issue önerdi, ancak anladığım kadarıyla, bu snippet'te kopya başlatma kullanmıyorum. Burada olanlara biraz ışık tutabilir mi?

(yukarıda, mesajı üreten derleyici GCC 4.8.2 olduğu;. Bununla birlikte, çınlama benzer bir hata mesajı döndürür)

+1

Varsayılan kurucu devralınmamış. –

+0

T.C. Nasıl yani? "Türetilmiş d1" satırında, açıkça 'Base()' yi görüyorum. –

+0

@ T.C. kelimelerin seçimi yanıltıcıdır. Elbette, kurucular devralınırlar - aksi takdirde, bunları türetilmiş sınıftan arayamazsınız. Sadece farklı sınıf için kullanılır. – SergeyA

cevap

10

sorun delete bir kopya kurucu işaretleme sağlamasıdır bu kullanıcı ilan, Bu, söz konusu sınıfın varsayılan yapıcısını (sizin durumunuzda Derived) siler. davranış bu basit kodda görülebilir: Bir yan not olarak

struct X 
{ 
    X(const X&) = delete; // now the default constructor is not defined anymore 
}; 

int main() 
{ 
    X x; // cannot construct X, default constructor is inaccessible 
} 

: Base::Base() miras olacağını bile, derleyici Derived(): Base(){} gibi görecekti. Ancak Derived silinir, bu nedenle Base::Base() numaralı telefonu arayabilir. Genel olarak, bir using Base::Base bildirimi, ilgili derleyici tarafından üretilen Derived(params): Base(params){} için sadece sözdizimsel şekerdir.

+0

Bu, eksik olduğum bağlantıydı. Asla bir şeyi silmenin asla "kişiselleştirilmesi" olarak sayılacağını düşünmemiştim. Teşekkürler! –

+0

@DavidNemeskey Evet, gerçekten kafa karıştırıcı, ama işte böyle. – vsoftco

+0

Standart terim * kullanıcı tarafından bildirildi *. –

4

Özel bir kurucu tanımladığınızda, varsayılan kurucuyu açıkça belirtmeniz gerekir. Yani

Derived::Derived() = default; 
4

Inheriting constructors, özel yapıcılar alamıyor - boş, kopyala, taşı. Çünkü kelimenin tam anlamıyla sormak istediğin şey neredeyse her zaman kötü bir fikir.


inceleyin:

struct base { 
    std::vector<int> data; 
    base(base const&)=default; 
    base(base&&)=default; 
    base(size_t n):data(n) {} 
    base()=default; 
}; 

struct derived:base { 
    using base::base; 
    std::vector<char> more_data; 
}; 

Eğer gerçekten varolmaya derived(base const&) istiyorsun? Veya base(base&&)? İkisi de umutsuzca derived dilim olur.

"Yanlışlıkla" gerçekleşen bu işlemlerin tehlikesi, onları isterseniz açıkça getirmeniz gerektiği anlamına gelir.


kopyalama/taşıma/default vektörlerin içine klonlanabilir varsayılan olarak, sadece ana sürümü, artı üyesi değişkenlerin vektörlerin içine klonlanabilir çağırmak olur. Onları ebeveyninizden miras almayı gerektiren (genellikle) bir ihtiyaç yoktur. Bununla birlikte, =delete, =default, veya bir kez bu özel sunuculardan birini tanımladığınızda, diğeri derleyici tarafından oluşturulmayı durdurur. Bu yüzden hala diğerlerine takılmak isterseniz =default'a ihtiyacınız var.

+0

Açıklama için teşekkürler. '= Varsayılan' bile kullanıcı bildirimi olarak sayılır? –

+0

@DavidNemeskey Hayır. İlk olarak, özensiz olduğum için. İkincisi, kullanıcı tarafından bildirilen bir ifade standartta (inanıyorum) tanımlandığından ve bunları kullanmaktan kaçındığım için dikkatli teknik anlamları vardır. Ama '= default' bazı efektlere sahip olabilir - eğer kopya ctor'unu varsayılan olarak seçerseniz, hareket ctoru bastırılır ve tersi de geçerlidir. [Canlı örnek] (http://coliru.stacked-crooked.com/a/e1e31f3323dc0855). Aynı şey, = varsayılan "nullary ctor" için de geçerli değil. [Canlı örnek] (http://coliru.stacked-crooked.com/a/0c77e82287c0427e) – Yakk

İlgili konular