2008-12-17 34 views
2

我想實現這樣的:現在如何將方法結果作爲參數傳遞給C++中的基類構造函數?

class Base 
{ 
    public: 

    Base(string S) 
    { 
    ... 
    }; 
} 

class Derived: Base 
{ 
public: 
    int foo; 
    string bar() 
    { 
    return stringof(foo); // actually, something more complex 
    }; 

    Derived(int f) : foo(f), Base(bar()) 
    { 
    }; 
} 

,這不工作,我想,是因爲巴()被調用派生構造函數foo的初始化之前。

我認爲添加一個類似bar()的靜態函數,它將foo作爲參數 - 並在初始化列表中使用它,但我想問問是否還有其他技術可以用來挖掘自己這一個...

編輯:感謝您的反饋 - 這是我將如何處理靜態功能。不知道如果靜態和非靜態函數之間的過載是太聰明瞭,但是......

class Derived: Base 
{ 
public: 
    int foo; 

    static string bar(int f) 
    { 
    return stringof(f); // actually, something more complex 
    } 

    string bar() 
    { 
    return bar(foo); 
    }; 

    Derived(int f) : Base(bar(f)) , foo(f) 
    { 
    }; 
} 

回答

4

是,使用函數(靜態類方法或常規功能),其採用作爲參數,返回一個字符串是個很好的解決方案你可以從Derived :: bar調用這個相同的函數來防止代碼重複。所以,你的構造是這樣的:

Derived(int f) : Base(stringof(f)), foo(f) {} 

我第一次發出呼叫的基本構造在列表中強調其中初始化發生的順序。初始化程序列表的排序沒有效果,因爲所有類成員都按照它們在類體中聲明的順序進行了初始化。

這是一個非常乾淨的,functional方法的問題。但是,如果你還是想權衡替代品則可以考慮使用composition,而不是繼承的派生和基類之間的關係:

class Base { 
public: 
    Base(string S) { ... } 
    void bat() { ... } 
}; 

class Derived { 
    Base *base; 
    int foo; 

public: 
    Derived(int f) : base(NULL), foo(f) { 
     base = new Base(bar()); 
    } 
    ~Derived() { 
     delete base; 
    } 

    string bar() { 
     return stringof(foo); // actually, something more complex 
    } 

    void bat() { 
     base->bat(); 
    } 
}; 

您需要考慮pros和缺點您的具體情況。通過派生參考Base,您可以更好地控制初始化順序。

+0

HMM這與平普爾成語組合將是很好 – 2008-12-17 17:36:42

+0

尼斯 - 然而的組合物中的缺點是,以暴露基方法需要「蝙蝠狀」存根的數目。 – Roddy 2008-12-17 19:26:43

+0

真的!我想你會因爲這個原因而堅持計劃A. – 2008-12-17 21:10:45

0

我一直想要這樣做,但我最終放棄了。
任何合適的函數調用都可以用作Base()的參數。
另一種選擇是向Base添加和替代構造函數,它接受一個int並將其轉換爲「string」本身。

+0

「替代構造函數」並不好,因爲轉換邏輯基本上是派生類的一部分。 – Roddy 2008-12-17 16:53:57

4

您只能在初始化程序列表中調用靜態函數。你在代碼中的方式:

class Derived: Base 
{ 
public: 
    int foo; 
    string bar() 
    { 
    return stringof(foo); // actually, something more complex 
    }; 

    Derived(int f) : foo(f), Base(bar()) 
    { 
    }; 
} 

仍然會初始化Base,然後是foo。在構造函數初始值設定項列表中寫入內容的順序無論如何不重要。它總是構建順序:

  1. 首先,所有的虛基類
  2. 然後在它們出現在基類列表
  3. 然後在所有成員對象的順序非虛基類它們是在類定義中定義的。

因此,您最終會以未初始化的值調用stringof。此問題已在boost::base_from_member中解決。還要注意,在所有基類的所有構造函數初始值設定項完成之前調用任何非靜態成員函數都是未定義行爲。

調用靜態函數,但是,完全是罰款:

class Derived: Base 
{ 
public: 
    int foo; 
    static string bar(int f) 
    { 
    return stringof(f); // actually, something more complex 
    }; 

    Derived(int f) : Base(bar(f)), foo(f) 
    { 
    }; 
} 
2

的基類的構造函數總是被初始化派生類的其他成員之前調用;你的編譯器應該給你一個警告,讓初始化器的順序錯誤。唯一正確的解決方案是讓bar()這需要f作爲參數的靜態方法。

1

的構造爲,井,構建對象。這意味着,直到它返回時,那裏沒有對象,因此調用成員函數不會可靠工作。正如其他人所說,使用靜態函數或非成員函數。

0

只需將構造代碼的初始化()函數,從構造函數中調用它。這比靜態/非靜態重寫或類似的更簡單。

相關問題