2017-09-27 25 views
10

Genellikle bir std :: find yaptığımda üçüncü argüman olarak bir yüklemeyi koyacağım, ama bu sefer farklı bir şekilde yapacağımı düşündüm. Neden işe yaramadığını anlamak.Neden bu std :: bu nesneleri karşılaştırılamıyor

#include <iostream> 
#include <vector> 
#include <algorithm> 

struct RenderJob 
{ 
    RenderJob() {}; 
    int renderJob_ID; 
    bool operator==(RenderJob& rhs) { return rhs.renderJob_ID == this->renderJob_ID; } 
}; 

int main() 
{ 
    RenderJob foo; 
    RenderJob foo2; 
    foo == foo2; // Works 

    std::vector<RenderJob> renderJobs; 

    std::find(renderJobs.begin(), renderJobs.end(), foo); // Doesn't work 
} 

ikili "==" hayır operatör tip RenderJob bir solak işlenen alan (veya kabul edilebilir dönüştürme yoktur) cevapları için

Düzenleme :: Kuyu sayesinde hangi bulundu . o bir örnek olarak

RenderJob foo; 
    RenderJob foo2; 
    foo == foo2; // Works 

    std::vector<RenderJob> renderJobs; 

    std::vector<RenderJob>::const_iterator constit = renderJobs.begin(); 

    *constit == foo2; // Doesn't work 

Hatta daha basit başarısız nedeni işte bazı örnekler:

const RenderJob* pToRenderJob; 

*pToRenderJob == foo2; // This fails because the pointed to 
         // object is const, and cannot call the 
         // operator== function because the actual function 
         // definition is not const. 

o tersi olsaydı:

foo2 == *pToRenderJob; // This would fail because the 
         // operator==(RenderJob&) the actual argument 
         // is not const. Very subtle rules 
+0

Örneklerinizde, '* = = foo2' veya' * pToRenderJob == foo2' işlevini yapamazsınız, çünkü '= =' '' const' sol işleneninin '* bu 'olmasını sağlamak için bildirilmez. . Eğer sınıf bir fonksiyona sahip olsaydı, aynı şey olurdu: “f()” - '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' yapamazsınız. Ama eğer bu işlevi 'void f() const' 'olarak değiştirirseniz, her ikisi de iyi olur. – aschepler

+0

Teşekkürler, birçok kural yavaşça ayarlanıyor. – Zebrafish

+0

Ayrıca sınıfınızda "renderJob_ID" öğesini tanımlamanız gerekir: int renderJob_ID {} ​​'. Başlatılmamış nesnenin terk edilmesi, erken optimizasyondur. Örneğinizde foo.renderJob_ID ve foo.renderJob_ID * * belirsiz değer * var ve std :: vector renderJobs (10) 'ifadesini 10' renderJobs' şeklinde tanımlamak isterseniz, bu 10 nesnenin kendi renderJob_ID'si * belirsiz değer *. Bu nedenle kodunuz, operatöre == argümanı ekledikten sonra bile çalışmaya devam etmeyecektir. – Oliv

cevap

14

Sen const eleme bıraktığı.

bool operator==(const RenderJob& rhs) const { ... } 
+2

Evet, teşekkürler. Özellikle const RenderJob, fonksiyondan sonraki değil. Ancak bunu anlayamadım, çünkü operatör == aşırı yüklenme nedeniyle onları kendim karşılaştırabilirim, std :: sadece işleç == işlevini kullanamaz mı? – Zebrafish

+4

Her ikisi de const olmalıdır. Derleyici, const verileri üzerinde bir operatör aradığında, const davranışını garanti etmeyen operatörleri dikkate almayı reddeder. –

+0

Şimdi anlıyorum, ama yine de, sorudaki ek örneğimde, sağ tarafın bir kurgusu yok ve bu yüzden konstrüksiyon operatörünü çağırması gerektiğini düşündüm. const olmayan. – Zebrafish

5

Bana bir const-doğruluk sorunu gibi görünüyor. Sadece geçicileri değildi düz nesneleri geçen çünkü kendinizi çalışmış karşılaştırma yapmak

bool operator==(RenderJob const &rhs) const { 
    return rhs.renderJob_ID == this->renderJob_ID; 
} 

, ne de nitelikli const vardı: artık şöyle bir şey deneyin. std::find ile karşılaştırma işlevi (en azından genellikle) koleksiyondaki nesneye bir referans alır (normalde yapıda kalifiye olur), bu yüzden bir yapı kalifiye referansı alması gerekir.

+1

Oh, anladım, işe yaradı. Ama onları kendimle karşılaştırdım. Std :: 'deki karşılaştırma işlevi, yalnızca işleç == işlevini kullanır mı? – Zebrafish

+1

@Zebrafish 'find', const referansıyla karşılaştırılacak değeri alır. –

3

Ama bu yine de duyu yapmaz, yukarıdaki örnekte, sağ taraf olmayan constoperator== gitmeli, hangi sabit değildir, hangi foo2 olduğunu. const ve const olmayan genel bir kural yoksa, karşılaştırılamaz.

const ve sivil const nesneler karşılaştırılamaz o dildeki herhangi bir kural yoktur. Uygun const niteleyicileri kullanarak karşılaştırılabilir olduğundan emin olmalısınız.

hat

*pToRenderJob == foo2; 

pToRenderJob olmayan bir const üye işlevi çağırmak için kullanılamaz çünkü çalışmıyor

pToRenderJob->operator==(foo2); 

eşdeğerdir. foo2 burada sorun değil.Eğer

foo2 == *pToRenderJob 

kullanırsanız

sizin işlevi olmayan const başvuru bekler iken işlevin bağımsız değişkeni const nesne olduğundan aynı zamanda bir sorundur Yani

foo2.operator==(*pToRenderJob) 

eşdeğerdir. Bir kez daha foo2 problem değil.

fonksiyonu bir const üye işlev yapma ve const referans operatör her iki tarafında const ve non-const nesnelerin tüm kombinasyonları herhangi bir sorun olmadan kullanılabilir kesinleştirir argüman adrestir.

+0

Bu çok ilginç, yani gerçek işlev yapısını oluşturduğumda çalıştıran * pToRenderJob == foo2. Çok ilginç ve ince kurallar. – Zebrafish

+0

@Zebrafish. Bu kurallara alışmak biraz zaman alır, fakat bundan daha fazla, dili daha derinden anlayarak, kurallar anlam kazanmaya başlar. –