2014-02-07 60 views
1

我繼承了兩個類,TFoamIntegrand和IBaseFunctionMultiDim,它們都是抽象類。我遇到的問題是我希望能夠使用克隆成員函數,該函數對於IBaseFunctionMultiDim是一個沒有參數的純虛擬,對於TFoamIntegrand,它不是TFoamIntegrand中的純虛擬,而是具有參數(具有默認值)。C++多繼承,虛方法重載問題和協變返回類型

class TObject { 
    public: 
     virtual TObject *Clone(const char *newname="") const; 
    ... 
}; 

class TFoamIntegrand : public TObject { 
public: 
    virtual Double_t Density(Int_t ndim, Double_t *) = 0; 
    ... 
}; 

class IBaseFunctionMultiDim { 
    public: 
     /** 
     Clone a function. 
     Each derived class must implement his version of the Clone method 
     */ 
     virtual IBaseFunctionMultiDim * Clone() const = 0; 
    ... 
} 

我可以把它編譯的唯一方法就是要做到:

class InSANEDiffXSec : public TFoamIntegrand, public ROOT::Math::IBaseFunctionMultiDim { 
    public: 
     virtual ROOT::Math::IBaseFunctionMultiDim* Clone() const ; 
    ... 
} 

當然,這產生大約隱藏克隆與參數的警告。我已經嘗試了以下,但我得到協變返回類型錯誤。

virtual ROOT::Math::IBaseFunctionMultiDim* Clone(const char * newname = "") const ; 
    virtual InSANEDiffXSec* Clone(const char * newname = "") const ; 

根據我對協變返回類型的理解,我認爲上面的最後一個版本是正確的。我在這裏錯過了什麼?

在此先感謝!

編輯:這是一個完整的例子:

class A { 
    public: 
    virtual A* Clone(const char * name="") { return(new A());} 
}; 

class B { 
    public: 
    virtual B* Clone() = 0; 
}; 

class C : public A { 
    public: 
    virtual double Density(int ndim, double *) = 0; 
}; 

class D : public C, public B { 
    public: 
     virtual double Density(int ndim, double *x) { 
     return 0.0; 
     } 
     //virtual D* Clone(const char * name="") { return(new D());} 
     virtual B* Clone() { return(new D());} 
}; 

它編譯。更改爲註釋行給出:

test.h: In member function ‘virtual D* D::Clone(const char*)’: 
test.h:24:62: error: cannot allocate an object of abstract type ‘D’ 
     virtual D* Clone(const char * name="") { return(new D());} 
                  ^
test.h:19:7: note: because the following virtual functions are pure within ‘D’: 
class D : public C, public B { 
    ^
test.h:11:17: note:  virtual B* B::Clone() 
     virtual B* Clone() = 0; 
       ^
test.cxx: In function ‘int main()’: 
test.cxx:7:18: error: cannot allocate an object of abstract type ‘D’ 
    D * d = new D(); 
       ^
In file included from test.cxx:2:0: 
test.h:19:7: note: since type ‘D’ has pure virtual functions 
class D : public C, public B { 
+0

請閱讀http://sscce.org並將其應用於您的問題。擺脫殘酷! – Yakk

+0

我有很多鏈接來編寫有據可查的代碼,但我只能發佈一個鏈接,因爲我在這個網站上缺乏聲譽。 – whit2333

+2

我要求*少代碼*不多。請閱讀http://sscce.org – Yakk

回答

1

這編譯:

class TObject { 
    public: 
     virtual TObject *Clone(const char *newname="") const = 0; 
}; 

class IBaseFunctionMultiDim { 
    public: 
     virtual IBaseFunctionMultiDim * Clone() const = 0; 
}; 

class InSANEDiffXSec : 
    public TObject, 
    public IBaseFunctionMultiDim 
{ 
    public: 
     virtual InSANEDiffXSec* Clone(const char* newname) const 
     { 
     return nullptr; 
     } 
     virtual InSANEDiffXSec* Clone() const 
     { 
     return Clone(nullptr); 
     } 
}; 

,但我沒有從你的代碼,這似乎並不相關刪除的東西。

+0

那麼這裏發生了什麼?默認參數沒有照顧第二個克隆? – whit2333

+1

@ whit2333默認參數是在* call site *處發生的事情。函數'foo(int x = 7)'是一個函數'foo(int x)',帶有指令「,如果調用者不給你一個'x',則使用'7'」。該函數仍然需要1個參數,即'int'。因此,你的'const char * newname =「」'overload是該函數的'const char *'版本的重載,並且不會重載該函數的0參數版本。 – Yakk

+0

謝謝。構造函數是否一樣?如果我只有一個具有默認參數的構造函數,它是否仍將其用作默認構造函數? – whit2333