2011-08-03 46 views
3

我有一個Visual Studio 2008 C++應用程序,我在其中創建了一個自定義流緩衝和流實現。我已經使用Angelika Langer給出的方法來創建流詳述如下:創建自定義標準流實現時的編譯器警告

class MyOutputStream_3 : private MyStreamBuf, public ostream { 
public: 
    MyOutputStream_3() : ostream((MyStreamBuf*) this), ios(0) {}; 
    virtual ~MyOutputStream_3() { sync(); } 
    // ... 
}; 

但是,Visual Studio中給了我一個warning

warning C4355: 'this' : used in base member initializer list 

的代碼工作正常,但我擔心的編譯器告訴我,我所做的或者在某些情況下可能會中斷,或者可能是不可移植的。

這個事情我可以忽略在這種情況下,或者我應該怎麼做才能解決我的問題?

+1

_Never_忽略警告。 –

+0

@Tomalak - 你說的代碼是不正確的,我應該改變它?如果是這樣,怎麼樣?或者,你是否說我應該記住這個警告,因爲未來的改變很容易使代碼不正確? – PaulH

+0

至今我一直無法確定爲什麼代碼可能不正確/未定義。這並不意味着它不是,而且你的編譯器比我更瞭解該語言。也可能有一個「小心;你的代碼很容易發生絲毫變化的嚴重錯誤!」因素,這也是不能忽視警告的理由。它們不是爲了好玩而發射的! [我並不是說你必須改變你的代碼;只是不要完全忽視警告。有一箇中間地帶。 :)] –

回答

1

的C++標準03本有位記爲12.6.2/7 「Initializaing基地和成員」:

[注意:因爲mem-initializer是在構造函數的範圍內求值的,所以這個指針可以在mem-initializer的表達式列表中用來引用被初始化的對象。 ]

由於指針未被完全初始化,我認爲會發出警告,因爲存在一些潛在的危險。只要你的基地實際上並沒有使用對象的未初始化部分,直到它們被初始化後,你應該沒問題。

由於MSDN文檔的警告(http://msdn.microsoft.com/en-us/library/3c594ae3.aspx)提到:

實際上,你已經通過了一個指向未構造的對象到另一個構造。如果其他構造函數訪問任何成員或調用成員函數,結果將是未定義的。

+0

我確信我讀過一次,在派生實例完全構造之前將'this'轉換爲基類型是UB。 –

+0

順便說一句,'[2003:9.3.2]'似乎並沒有在成員初始化程序中實際定義'this'的類型。 –

+0

@Tomalak:給定'struct D:B {D():B(this){}};',出現在初始化列表中的'this'是類型'D *'。在C++ 03§12.7/ 2中有一個例子,儘管這種行爲也是由虛擬函數調度的方式所暗示的。 (我承認我不知道規範文本在哪裏指定了這個)。 –

2

它警告你在初始化列表中使用this因爲在技術上,this還沒有因爲構造尚未完成執行還不存在(也沒有任何成員對象的構造函數),並將它傳遞給函數可能會導致問題,當他們嘗試使用該對象(其中包含其構造函數尚未被調用的對象)。

如果您只是稍後存儲指針,代碼應該可以工作。但是當你回到這個代碼並忘記你不應該使用那個指針時,你可能會犯一個錯誤,並且不能解釋你的程序崩潰的原因。

以下是一個警告頁面微軟:http://msdn.microsoft.com/en-us/library/3c594ae3.aspx

0

順便提一句,這隻有在你明確使用mem-initializer列表中的this時纔會發生。傳遞尚未構造的成員變量的地址不會引發C4355。

如果您需要證明,請查看fstream的構造函數。