2012-09-08 90 views
1

我有雞< - >雞蛋問題。
我想創建一個容器類的接口,以便我可以強制實現特定的attr訪問器和其他方法,同時我希望能夠從Containers構造函數中調用這些方法。
但是,正如我們所知,由於調用層次結構中的構造函數的順序,因此從構造函數調用虛方法將調用基類方法。
所以問題是我需要虛擬方法來強制執行,但這是我不能在構造函數中調用的東西。
編輯:我想要當我必須實現容器類(C1,C2 ...)被迫實現特定的方法,第二我希望能夠在容器構造函數中使用這些方法。簡單地說,我想實現INTERFACE需求,只聲明混用。謝謝
你如何解決這個問題?
以下是代碼示例。

虛擬方法和構造函數?

#include <iostream> 
using namespace std; 

class Base { 
public: 
    virtual void myvirt() { cout << "Base::virt()" << endl; }; 
}; 

class C1 : public Base { 
public: 
    C1() {cout << "C1()" << endl; C1::myvirt(); }; 
    C1(int i) { cout << "C1(int)" << endl; } 
    void myvirt() { cout << "C1::virt" << endl;} 
}; 


class C2 : public Base { 
public: 
    C2() {cout << "C2()" << endl; C2::myvirt();}; 
    C2(int i) { cout << "C2(int)" << endl; } 
    void myvirt() { cout << "C2::virt" << endl;} 
}; 

template<class C = C1> 
class Sc: public C { 
public: 
    Sc() : C() { cout << "Sc()" << endl; }; 
    Sc(int n): C(n) { cout << "Sc(int)" << endl; }; 

}; 


int main() { 
    Sc<C2> $sx(12); 
    return 0; 
} 

正如我問的是有一些方法來強制執行的子孫類特定構造的()。 就像「虛擬建設者」。

+2

目前尚不清楚你想要什麼。 –

+0

你試圖調用哪些特定的派生方法?在構造對象之前沒有通用的解決方案來調用對象的成員函數。 –

+1

在C1的構造函數中調用一個虛函數會調用C1的重載,所以目前還不清楚你需要做什麼,你還沒有做。 –

回答

5

只是使構造函數變得無足輕重,然後在構造函數返回後調用某種初始化函數來完成對象的構造。您也可以使用clone成語,具體取決於您想要決定構建什麼樣的對象。

你也可以有一個包裝類,它的構造函數首先構造內部類,然後調用它的虛擬初始化函數。

更新:你可以用這樣的:

Class Wrapper : public Inner 
{ 
     public: 
     Wrapper(...) : Inner(...) 
     { 
      init(); 
     } 
     virtual ~Wrapper(); 
} 

現在,你可以做

Wrapper foo(whatever); 

你也可以使用foo就像一個Inner

+0

嗯......謝謝,包裝方案將如何?看起來克隆/創建模式會起作用,我只是不想聲明像這樣的變量「Sc var = x.create(5)」,但只是說「Sc var(5);」 – user1019129

3

您不應該在施工或銷燬期間首先調用虛擬功能。這根本不是一個好習慣。

從C++有效,第3版的第9項摘錄:

有一個很好的理由,這看似有悖常理的行爲。由於基類構造函數在派生類構造函數之前執行,因此派生類數據成員在基類構造函數運行時尚未初始化。如果在基類構造過程中調用的虛函數轉到派生類,派生類函數幾乎肯定會引用本地數據成員,但這些數據成員尚未初始化。這將是不確定的行爲和深夜調試會話的不間斷票據。調用尚未初始化的對象的部分內在地是危險的,所以C++讓你無法做到這一點。

http://www.artima.com/cppsource/nevercall.html

+0

是的,我知道..這就是爲什麼在這裏問任何解決方法..即使用虛擬方法獲得相同的效果W/O – user1019129