2015-02-10 58 views
-2
[Global Scope] 

myClass *objA, *objB, *obj; 
int objnum; 

我想和objAobjB之間切換,或者將其分配到obj,所以在main()我有奇怪的行爲一個函數被稱爲在兩個對象之間切換:C++ 11類,指針和全球範圍內聲明

void switchObjects() 
{ 
    if (++objnum > 1) objnum = 0; 
    obj = objnum == 0 ? objA : objB; 
} 

而在我使用該對象的函數中,我有:

void doYourJob() 
{ 
    int res = obj->work(); 
} 

現在奇怪的是,如果我不分配obj要麼objAobjB,它仍然有效。相反,我會期待一個例外。即使我做obj = NULL;,它仍然有效!這是什麼巫術?

OK,我公司可提供帶來同樣的結果不同的例子,不使用NULL指針:

myClass *obj[2]; 
int objnum; 

void switchObject() 
{ 
    if (++objnum > 1) objnum = 0; 
} 

void doYourJob() 
{ 
    res = obj[objnum]->work(); 
} 

int main() 
{ 
    obj[0] = new myClass(parameters...); 
    obj[1] = new myClass(parameters...); 

    objnum = 0; 
} 

與上面的代碼,無論objnum的價值,我仍然得到這兩個對象工作在一起,即使我只在一個實例上調用work()

如果我這個替換功能doYourJob()

void doYourJob() 
{ 
    int res1 = obj[0]->work(); 
    int res2 = obj[1]->work(); 
} 

我總是得到的結果增加了一倍,因爲如果我每個對象調用函數work()兩次。

+0

你不能指望任何未定義的程序*。 – molbdnilo 2015-02-10 13:35:03

+4

在空指針上調用成員函數是未定義的行爲。如果成員函數實際上沒有使用任何類成員,它通常會工作。 – 2015-02-10 13:35:17

+0

我發佈了一個與空指針無關的例子,任何人都可以給我一個線索? – 2015-02-10 14:03:43

回答

4

考慮一個簡單的例子:

#include <iostream> 

struct X 
{ 
    void foo() { std::cout << "Works" << std::endl; } 
}; 

int main() { 
    X* x = nullptr; 
    x->foo(); 
} 

對於大多數編譯器,並在大多數平臺上,該代碼會出現做工精細,儘管在一個空指針已經叫foo。但是,行爲在技術上是undefined。也就是說,如果你這樣做,C++語言不會限制可能發生的情況。

它爲什麼有效?那麼,調用成員函數只需要知道被調用的對象的類型。我們知道x指向X,所以我們知道要調用哪個函數:X::foo。在很多情況下,知道指針是否指向真實對象可能很困難,甚至不可能,所以編譯器只是讓它發生。在這種情況下,函數的主體實際上並不依賴於實際存在的對象,所以它正常工作。這不是你可以依賴的東西。

+0

我已經更新了我的帖子,並給出了相同的結果。你可以看一下嗎?它仍然需要做空指針嗎? – 2015-02-10 14:04:35

+0

@MarkMiles [無法重現](http://ideone.com/kI36Bj)。您需要發佈一個新的問題,並提供一個簡短的,可編輯的示例供任何人提供幫助。 – 2015-02-10 14:09:27

+0

嗯,我不能在一個簡單的例子上重現它...我的實際程序是更大的方法,涉及到許多內存分配,定時器,回調,套接字,實時音頻等......問題可能在其他地方。我試圖在這個例子中簡化它(http://ideone.com/bjQ1s8),但在我的實際程序中,無論我使用類指針的索引,我都沒有得到任何錯誤,它仍然有效。 – 2015-02-10 14:28:51