2009-03-19 44 views
10

Bu tür bir parça bana kırılmış gibi gözüküyordu, ancak this'un null olduğu ortaya çıkıyor. Sadece sahip herhangi bir yolu yoktur bu bizeğer (! This) {return false; }

if (!this) { return false; } 

sahip null

o MyObject::func() içinde normal bir yöntem çağrısı gibi

myObject->func(); 

içinde olduğunu nasıl olabilir alamadım null (?) yönteminin içine girmek yerine NullPointerException atmak için ilk satır?

+0

Bu .net özgü midir? - Bu etiketi değiştirmek isteyebilirsiniz, C++ kullanıcıları çok süzülecek. Net –

+1

NullPointerException, bunun bir C++ sorusu olmadığını düşünüyor. C#? – Tom

cevap

22

Eğer varsa: Bundan sonra ne olacak func sanal olup olmadığına bağlıdır

MyObject *o = NULL; 

o->func(); 

. Eğer öyleyse, o zaman çökecektir, çünkü vtable'ı almak için bir nesneye ihtiyacı vardır. Ancak sanal değilse, çağrı bu işaretçi NULL olarak ayarlanmış olarak ilerler.

Standartın bunun "tanımlanmamış davranış" olduğunu söylediği, her şeyin olabileceği, ancak tipik derleyicilerin yalnızca işaretçinin NULL olup olmadığını denetlememesi için kod oluşturduğuna inanıyorum. Bazı iyi bilinen kütüphaneler, tanımladığım davranışa güvenir: MFC, bir boş gösterici üzerinde çağrılabilen SafeGetHandle gibi bir işlevi vardır ve bu durumda NULL değerini döndürür.

Sen yeniden kullanılabilir yardımcı işlevi yazmak isteyebilirsiniz:

void CheckNotNull(void *p) 
{ 
    if (p == NULL) 
     throw NullPointerException(); 
} 

Ardından this dahil tüm argümanları kontrol etmek için bir fonksiyonun başlangıcında bu kullanabilirsiniz:

CheckNotNull(this); 
+0

Sadece açıklığa kavuşturmak için ... dereferencing NULL standart tarafından tanımlanmamış bir davranış. MFC buna bağlı olmamalı. Uygulama tanımlanmış olsaydı, işler farklı olurdu. Bu, bir yarış koşulunun "düzeltilmesi" için zayıf bir girişim olduğu yönünde. –

+0

Bu hikayenin uygun olduğunu düşünüyorum: http://www.gotw.ca/conv/002.htm –

+0

Hikayeye alternatif ahlaki: CheckNotNull'u uygulayın ve "Bir pislik, Bob olmayın" mesajıyla bir istisna atın !" –

1
if(this == null) 
    throw new NullPointerException; 
if(!this) 
    return false; 
+0

Neden özel duruma bir işaretçi atarsınız? –

+0

Ve neden bunu NULL için iki kez sınayın? – Eclipse

+0

Kodunuz C# gibi görünüyor değil mi? – mmmmmmmm

-1

bu = = null, yalnızca silinmiş bir nesnede bir yöntem çağırıyorsanız veya bellekte bir şey yazmıyorsa (ve özellikle de bu işaretçinin özellikle işaretçisini üzerine yazıyorsa) oluşmalıdır.

Kodunuzda gerçekten neyin yanlış olduğunu araştırmak yerine, bununla ilgili yanlış olanları araştırmalısınız.

+0

Bir nesneyi silme, işaretçisini null değerine ayarlamaz. Mark Ransom'un yorumu için –

+0

+1. – Tom

0

bu işaretçi Bu gibi durumlarda geçersiz hale gelebilir:

class Test 
{ 

public: 
    bool f(); 

private: 
    int m_i; 
}; 


bool Test::f() 
{ 
    if(!this) 
    { 
     return false; 
    } 

    m_i = 0; 
    return true; 

} 


int main(int argc, char **argv) 
{ 
    Test* p = new Test; 
    delete p; 
    p = NULL; 

    p->f(); 
} 

Birinin erişim ihlali istisna önlemek için hızlı kesmek öyle oldu.

+0

Sadece bu f aramak için dener kadar düşmez sadece şaşırdım ... p NULL ise, p-> bir şey seg-fault olmalıdır ... –

1

this için null olması mümkündür. Bu kodun, nesnenin henüz başlatılmamış veya silinmiş olduğu bir yarış koşulunu (kötü bir şekilde) tespit etmeye çalıştığını sanıyorum.

+0

Eğer "bu" değiştiremezsiniz . bu bir rengin. (= "bu" bir nesne değildir). Bunu böyle düşünebilirsiniz, "ben" in bu işaretçi olduğunu hayal edin: T * self_ = this; #define self (self_ + 0) // yapamadım (self + 0) = ... –

+0

Ugh, haklısın."Ama yazılmayacak" demek istedim. –

1

(bu == NULL), standarda göre tanımlanmamış bir davranıştır. Ben Bu çeki :)

aşağıdaki arama yapmak varsayalım kaldırmak gerektiğini düşünüyorum:

((CSomeClass*) 0)->method(); 

davranış zaten tanımsız, neden CSomeClass :: yönteminde bu == NULL kontrol gerçekleştiriyor rahatsız?

REDAKTE: Ben senin derleyici idare edecek varsayın (0 == bu) Eğer üye değişkenleri kullanmak istemiyorsanız, ama nerede o sanal masa işaretçi bulur? Bu durumda, sınıfınız polimoprizm kullanamaz.

+0

Check-in'i yapmanın bir nedeni, derleyiciniz sizin için yapmazsa standardı düzgün bir şekilde uygulamaktır. –

+0

Ben ilk etapta NULL denir, o zaman kontrol hiç gerekli olmazdı. veya - kontrol ettiğimde - o zaman arama zamanında. arayanın böyle imkansız şeyler yaptığı zaman neden aranan endişelenmeli? Bu durum için bir iddia içeren iyi bir akıllı işaretçi tüm doğru olduğunu düşünüyorum –

+0

evet, kod (ass in method) veya akıllı işaretçi içinde assert (obj) sorunu tespit etmemize yardımcı olur. Genelde Genelde pek çok geliştiriciyi gördüm, hiç kimsenin asla gerçekleşmemesi, iddia edilmesi ve hangi şeyin kontrol edilmesi gerektiğini düşünmüyorum. – bayda

2

Bu tür hataları (tasarım yoluyla) yakalamanın bir yolu, boş bir işaretçi argümanı ile oluşturulmasını sağlayan bir işaretçi sarmalayıcı sınıfı (bir shared_ptr benzeyen) kullanmaktadır. Ayrıca, dereferans edildiğinde de atabilir, ama bu biraz geç - hiç yoktan iyidir, sanırım.

+0

İlk boost :: shared_ptr'nin atılacağını düşündüm. ama baktıktan sonra cevabımı silmek zorunda kaldım, çünkü bu bir şey değil: çünkü görünüşe göre bir şey atılmış olsun ya da olmasın uygulamaya dayanıyor. Ama yine de, GCC'mde bir iddianın başarısızlığını görüyorum - hiçbir şeyden daha iyisi :) –