2010-08-18 39 views
16
class A; 

class B { 
public: 
    B(A& a) : a(a) {} 
private: 
    A& a; 
}; 

/* Method 1 */ 
/* warning C4355: 'this' : used in base member initializer list */ 
/* 
class A { 
public: 
    A() : b(*this) {} 

private: 
    B b; 
}; 
*/ 

/* Method 2 */ 
/* But I need to manually perform memory dellocation. */ 
class A { 
public: 
    A() { b = new B(*this); } 
    ~A() { delete b; } 

private: 
    B* b; 
}; 

int main() { 
} 

目前,當我嘗試初始化B中的參考,我使用的方法。然而,方法1個意志標誌我警告其是可以理解的。初始化參考 - 警告C4355:「這個」:在基地成員初始化列表中使用

因此,我必須回退使用方法2,通過使用動態內存分配。

有沒有更好的方法可以使用,而不需要手動內存分配/解除分配(OK。我知道智能指針)?

我更喜歡方法1,只是說我對這個警告並不滿意。

回答

12

注意這是一個警告(所以它是危險的不是非法的)。

編譯器擔心的是您傳遞的指針未完全初始化的對象。因此,如果指針在B類構造函數中使用,則處於未定義行爲狀態。

所以,如果你確實使用這個,你可以做的唯一的事情就是將指針賦給一個成員變量(引用或指針)。 但注意要小心賦值給一個變量,因爲你可能會調用一個隱式轉換(我不確定這是否是一個實際的問題,但是直到完全形成該對象之前RTTI纔可用)。

你想通過存儲參考來實現什麼?

8

這樣做是有效的。

但是,您必須確保(我的意思是您自己,編譯器無法做到這一點)this不用於調用虛擬函數,直到完全構造對象。

1

那麼,避免這個警告的一個顯而易見的方法是讓B存儲一個指向A的指針,然後你不必在B的構造函數/ A的初始化列表中初始化它,並且可以等到A的主體構造函數正在執行....

0

認真對待此警告。您的this對象尚未完全構建,傳遞並不安全(如果您不小心調用了this上的函數,則調用UB)。此外,還有其他內存管理技術。嘗試查找分配器的STL設計。

你也可以使用RAII /智能指針來達到同樣的效果。

或者,你想寫一個垃圾收集器/內存分析器的種類?

6

根據你在做什麼,一種方法可能是分解B需要的部分A,比從零件繼承A

struct bar_base; // interface foo wants 

struct foo 
{ 
    foo(bar_base& pX) : 
    mX(pX) 
    {} 

    bar_base& mX; 
}; 

struct bar_base 
{ 
    /* whatever else */ 
protected: 
    bar_base& get_base(void) 
    { 
     // getting `this` went here; safe because bar_base is initialized 
     return *this; 
    } 
}; 

struct bar : bar_base 
{ 
    bar(void) : 
    // bar_base is already initialized, so: 
    mX(get_base()) 
    {} 

    foo mX; 
}; 

很明顯,這取決於你在做什麼。這確保你永遠不會得到未定義的行爲。

但實際上,這只是警告。如果你答應在B的構造函數中從來不使用this,你的罰款,並可以沉默的警告是這樣的:

struct bar; 

struct foo 
{ 
    foo(bar& pX) : 
    mX(pX) 
    {} 

    bar& mX; 
}; 

struct bar 
{ 
    bar(void) : 
    mX(self()) 
    {} 

    foo mX; 

private: 
    bar& self(void) 
    { 
     // fools the warning 
     return *this; 
    } 
}; 

確保你知道你在做什麼,雖然。 (也許它可以重新設計?)

相關問題