2010-10-23 82 views
6

我想創建一個以某種父子關係關聯另一個類的類。爲此,「孩子」課程需要提及其父母。在C++中,在構造期間用'this'指針初始化一個類成員

例如:

template <typename T> 
class TEvent { 
    private: T* Owner; 
    public: TEvent(T* parent) : Owner(parent) {} 
}; 

class Foo { 
    private: TEvent<Foo> Froozle; // see below 
}; 

現在的問題是,我不能直接初始化Froozle情況下,也沒有使用Foo的構造函數的instanciation列表,因爲this引用是不允許存在。除了增加另一種方法setParent(T*)(我不喜歡太多,因爲這意味着我必須將TEvent<>實例置於無效狀態),有沒有辦法實現這一點?

回答

11

在初始化列表中使用this是可以的,只要它不用於訪問任何尚未初始化的成員即可。

+0

他說什麼。只要你傳遞'this'的對象在構造過程中「不知道」觸及它(因爲這個對象'this'沒有被完全構造),這樣做很好,即使一些編譯器(特別是VC)發出警告。 – sbi 2010-10-23 21:43:18

+0

VC++是這裏的關鍵。它確實有效。好像我必須強行壓制那個「錯誤」。非常感謝! – sunside 2010-10-23 21:53:09

+1

我希望VC++只在ctor內的「this」成員訪問時發出警告。順便說一句,谷歌:: LogMessage類在[谷歌博客](http://code.google.com/p/google-glog)存儲「this」自己在mem-initializer列表ctor出於調試目的。我必須重新編譯#pragma警告(4355:禁用)才能在VC2010中工作。 – 2013-02-26 19:10:29

1

這是應該工作;實際上,

template<class T> 
class Child { 
private: 
    T *parent; 
public: 
    Child(T *parent) : parent(parent) {} 
}; 
class Parent { 
private: 
    Child<Parent> child; 
public: 
    Parent() : child(this) {} 
}; 

用g ++ 4.4.5和clang ++ 2.8編譯得很好。

什麼是你的失敗?

+0

「將警告視爲錯誤」的VC編譯器標誌和標有「錯誤消息」的MSDN文檔標題。 :)你是完全正確的 - 它的工作原理,我只是沒有看到它。非常感謝! – sunside 2010-10-23 21:52:06

10

從標準12.6.2/7「初始化鹼和成員」(重點煤礦):

名稱在 MEM-初始化的表達式列表中的構造的 範圍被評估爲其指定了 mem初始值設定項。

[實施例:

class X { 
    int a; 
    int b; 
    int i; 
    int j; 

public: 
    const int& r; 
    X(int i): r(a), b(i), i(i), j(this->i) {} 
}; 

初始化X::rX::a, 與 構造參數i的值初始化X::b,初始化 X::i與 構造參數i的值,和 初始化X::j的值爲 X::i;這發生在每次創建class X的 對象時。 ]

[注:由於MEM-初始化是 在 構造的範圍進行評價,所述this指針可以 可以在 的MEM-初始化來指代 對象是表達式列表用於初始化。 ]

+1

看起來很瘋狂。 :D – sunside 2010-10-23 21:54:42

+0

這是否意味着「this」僅允許在ctor的mem-initializer列表中,還是允許在ctor的主體中?我已經嘗試過使用VC2010 ++中的ctor體內的「this」幾次,它全部編譯並運行正常,警告C4355禁用,但僅僅因爲它的工作並不意味着我被允許。到目前爲止,我還沒有在[開放標準文檔](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1905.pdf)中找到任何內容,允許在該機構內部提及「this」。 – 2013-02-26 19:21:02

+0

@DavidLee:在構造函數中,this指向正在構造的對象(就像在上面描述的初始化器列表中一樣)。你可以在構造函數體內使用'this'。 – 2013-02-26 20:49:27

1

如果你正在尋找相應的警告,只是這樣做:

class Foo 
{ 
public: 
    Foo() : 
    Froozle(get_this()) 
    {} 

private: 
    Foo* get_this() 
    { 
     return this; 
    } 

    TEvent<Foo> Froozle; // see below 
}; 

的間接足以阻止它。

+0

heh。爲什麼一個方法調用沒問題,但直接引用沒有?傻編譯:) – ephemient 2010-10-23 22:13:36

1

我不認爲這是對你的失敗,除非你有警告級別設置爲4(或類似的,我假設Visual Studio),並已啓用「治療警告作爲錯誤」。

基本上,這個警告是一件好事,因爲它不會讓你不小心使用this指針,當它指向什麼尚未構建。

但是,當你知道你在做什麼,無論this在初始化列表中傳遞,由此引發的警告和錯誤將會很煩人。

您可以通過裝飾構造擺脫它(再次,假設的Visual Studio)(除非它在類聲明的已定義 - 那麼你必須裝飾所有的類):

// warning C4355: 'this' : used in base member initializer list 
#pragma warning (push) 
#pragma warning (disable : 4355) 
some_class::some_class() 
: ... 
{ 
} 
#pragma warning (pop)