2017-01-26 23 views
19

benim son gcc g ++ derleyici, (sürüm> 6)Kontrol akışı referans artık

sınıf CodeWriter bir ostream referans değişkeni ile vardır ile eski bir proje derleme am derleme değil null ise.

class CodeWriter 
{ 
    //private: 
protected: 
    ostream &m_stream; 
public: 
    CodeWriter(ostream &stream):m_stream(stream){} 
    ~CodeWriter(){ 
    if(m_stream != NULL){ 
     m_stream.flush(); 
    } 
    } 
}; 

Sınıf oldukça büyük olduğundan yalnızca ilgili değişkenleri ve işlevleri ekledim.

Eğer yıkıcı görebileceğiniz gibi

NULL başvurusunu karşılaştırarak gibi görünüyor. Bu proje eski gnu alet zinciriyle uzun süre kullanıldığında iyi bir şekilde derlenmiştir.

Ama şimdi ostream ve long int ile karşılaştırmak için eşleşen operator != olduğunu söyleyen bir hata atıyor.

kimse değişikliği ardındaki mantığı açıklayabilir ve bunu düzeltmek nasıl? Gerekirse ben ek bilgi sağlamak mutlu olurdu

/bütün sınıfı bulunmaktadır.

if (m_stream) { 
    m_stream.flush(); 
} 

C++ 11

explicit bool için dönüşüm yaptı:

+9

Sen kodunu yanlış - bu (bir tür ya da başka bir aşırı operatörü çağıracağı) NULL karşı dere nesnesini karşılaştırır. Null referansı diye bir şey yoktur (ve bir tane de kontrol etmek mümkün değildir) –

+1

Re: "Sadece ilgili değişkenleri ve fonksiyonları dahil ettim" Evet! Teşekkür ederim! Kesinlikle doğru! –

+2

Ayrıca, _pointers_ ile null'ı karşılaştırmak için 'nullptr' değerini şimdi 'NULL' makrosu yerine C++ 11 veya daha sonra kullanmalısınız. (evet, orada bir işaretçiniz olmadığını biliyorum ama null çekinizin amacı ile konuşuyorum). –

cevap

32

kod NULL ile başvuru kendisi karşılaştırarak, ancak NULL ile başvurulan-nesne karşılaştıran değildir. Referanslar NULL olamaz ve referansın kendisini NULL ile karşılaştırması imkansızdır. ben uzun geri eski gnu toolchain ile kullanıldığında

Ve

Bu proje i derlenmiş.

davranış C++ 11 yana değişti çünkü.

C++ 11 önce, std::ostream dolaylı hata akımı ile tespit edildiğinde, bir boş gösterici döndürür operator void*() vasıtasıyla void* dönüştürülmüş olabilir. Dolayısıyla, kodun asıl amacı, akışının hatasız olup olmadığını kontrol etmektir.

C++ 11'den bu yana, dönüşüm işlevi false olarak döndürüldü; bu, hata oluştuğunda false değerini döndürür.Not olarak bildirilen işlev, bool için örtülü dönüştürme izin verilmez, bu nedenle, std::ostreambool (NULL ile karşılaştırılabilir için örtülü olarak dönüştürülemez) kod yeniden C++ 11 ile derlenmez bir tamsayı literal)). Bir C++ 11-uyumlu derleyici ile

sadece contextual conversions için bile açık dönüşüm fonksiyonları kabul edildiğini

if (m_stream) { 
    m_stream.flush(); 
} 

Not kodunu değiştirebilir. Yukarıdaki kod için m_stream sonra değeri if durumu için kullanılacak, explicit operator bool() ile bool dönüştürülür.

14

Akışları hep bu yüzden sadece bunu değiştirmek, bir boolean bağlamda değerlendirilebilir. Bu if (!m_stream.fail()) eşdeğerdir. C++ 11 öncesinde, bu kısa el Kontrol edilebilirlik Eski kod çalışmak için kullanılan yüzden void* bir (örtük!) Dönüştürme, temin edilmesiyle elde edilmiştir. ancak, @Arne belirttiği gibi, flush kendisi:

kod bu kontrol yerine sadece doğrudan m_stream.flush(); çağırıyor nedeni, dere başarısızlığın etkin istisnalar olabilir ve bu [güncelleme], atmak olabilir belki de başarısız ve atılabilir. hiçbir istisnası yoktur, sadece tamamen boole denetimi atlayabilirsiniz. [/ güncelleme]

+1

'if (m_stream)', '((m_stream.fail()) 'ise (' if (m_stream.good()) 'işlevini yerine getiriyorsa, (if (m_stream.fail())' ifadesine eşdeğer ise, bu "saf" ifadesiyle ilgisiz olsa da "çıktı akışları, çünkü" eof() 'değiller. Ayrıca, eğer niyet atmak değilse, o zaman çözümün kendisi de yetersizdir çünkü sifonun kendisi 'badbit'in ayarlanmasına ve 'badbit' için istisnaların etkinleştirilmesine neden olabilir. –

+0

@ArneVogel: Haklısın, teşekkürler! Sabit. –

+2

Akışın, akımın temizlenmeden önce geçerli olup olmadığını sınamanın nedeni, bir işaretçinin silmeden önce sıfır olup olmadığını sınamanın nedeni ile aynıdır: kitaplık belirtimini anlamadan "güvenli" olmak istemek. –

6

akış sınıfları önceden C++ 11 baz sınıflardan birinin bir operator void*() vardı. Tabii ki void* değeri NULL ile karşılaştırılabilir.

Geçerli C++ içinde bunun yerine, if ifadesinin bağlamında çalışan ancak genel bir ifadede olmayan bir explicit operator bool(). Biz explicit operatörleri yoktu zaman

bir void* kullanımı oldu bool bazı istenmeyen dönüşümleri önlemekti.