2013-03-27 71 views
0

我試圖加入一箇舊的代碼在C我現在的VC++項目:錯誤C2664和MyClass的衝突

// .h 
    class DMSinv : public CDialog { 
     double finte(double z); 
     double ITFStolz(double Zp1, double Zp2, double Zc); 
    }; 

// .cpp 
    double Zcglob; 
    double DMSinv::finte(double z) 
    { 
     return TFStolz(z, Zcglob); 
    } 

    double DMSinv::ITFStolz(double Zp1, double Zp2, double Zc) 
    { 
     int ierr; 
     Zcglob = Zc; 

     return (coteglob(&DMSinv::finte, Zp1, Zp2, 1.0e-10, &ierr)); 
    //error C2664: 'DMSinv::coteglob' : cannot convert parameter 1 from 'double (__thiscall DMSinv::*)(double)' to 'double (__cdecl *)(double)'  

    } 

的coteglob功能來自於舊的C部分,finte是將TFStolz函數傳遞給coteglob的中間函數。

我搜索的論壇,發現此相關的問題: How to convert void (__thiscall MyClass::*)(void *) to void (__cdecl *)(void *) pointer ,我試圖以這種方式適用於:

// .h 
    class DMSinv : public CDialog { 
     virtual double finte(double z); 
     double ITFStolz(double Zp1, double Zp2, double Zc); 
    }; 

// .cpp 
    double Zcglob; 
    extern "C" 
    { 
     static double __cdecl finteHelper(double z) 
     { 
      DMSinv* datainv = reinterpret_cast<DMSinv> (z); //error C2440: 'reinterpret_cast' : cannot convert from 'double' to 'DMSinv' 

      datainv->finte(z); 
     } 
    } 

    double DMSinv::ITFStolz(double Zp1, double Zp2, double Zc) 
    { 
     int ierr; 
     Zcglob = Zc; 
     double solution = coteglob(&finteHelper, Zp1, Zp2, 1.0e-10, &ierr); 
     return solution; 
    } 

,但仍然沒有工作。有人可以指導我如何適應它嗎?我還是一個新手,這似乎離我的知識還很遙遠。

在此先感謝!

+0

'DMSinv * datainv = reinterpret_cast < DMSinv >(z)' - 不應該轉換爲'DMSinv *'嗎? – SomeWittyUsername 2013-03-27 11:56:10

+0

我試過了,但是這給了我同樣的錯誤:'錯誤C2440:'reinterpret_cast':無法從'double'轉換爲'DMSinv *'' – madoro 2013-03-27 11:58:14

回答

0

不確定是否有可能做你想要的。我想到的唯一選擇是使用一些靜態變量來存儲DMSinv對象的地址。這限制了你1個線程和簡單的實施......

試試這個:

// .h 
class DMSinv : public CDialog { 
    double finte(double z); 
    double ITFStolz(double Zp1, double Zp2, double Zc); 

private: 
    static DMSinv* _current; 
    static double __cdecl finteHelper(double z); 
}; 

// .cpp 
double Zcglob; 
DMSinv* DMSinv::_current = 0; 
double DMSinv::finte(double z) 
{ 
    return TFStolz(z, Zcglob); 
} 

double DMSinv::ITFStolz(double Zp1, double Zp2, double Zc) 
{ 
    int ierr; 
    Zcglob = Zc; 

    _current = this; 
    return (coteglob(DMSinv::finteHelper, Zp1, Zp2, 1.0e-10, &ierr)); 
} 

double __cdecl DMSinv::finteHelper(double z) 
{ 
    return _current->finte(z); 
} 

這不是很好的解決方案海事組織,但我不知道有其他的方式。

PS 要刪除限制一個線程,你可以使用TLS插槽或VC++只是__declspec(thread)。 後者只需將__declspec(thread)加到_current就可以這樣:static __declspec(thread) DMSinv* _current;。但!!!注意每個線程變量的數量對於進程是有限的。在MSDN上閱讀更多信息。

UPDATE

Disclamer:只是爲了好玩。

理論上還有其他的機會。您可以將彙編代碼存儲在數組中,並附加到對象上。這個彙編代碼應該是一個__cdecl函數,它簡單地將__cdecl轉換爲基於eip寄存器的__thiscall。但是這不應該通過...來實現:D

+0

爲什麼它要求我在finiteHelper中返回一個值,在靜態時它是否需要? '錯誤C4716:'DMSinv :: finteHelper':必須返回一個值'。感謝'__declspec(thread)',看起來很有趣,我會看看。 – madoro 2013-03-27 12:56:08

+0

我已更新我的代碼以修復此錯誤。只需添加return,編譯器問你。 – 2013-03-27 12:59:13

+0

好的,謝謝,現在它編譯,但沒有運行,在某些時候打破。我會繼續研究爲什麼會發生這種情況,正如你所說這可能不是最佳解決方案,但感謝您的幫助! – madoro 2013-03-27 13:08:03

0

我不認爲你可以這樣做。你需要以某種方式將引用傳遞給你的對象(this)。在鏈接問題中,該函數的參數定義爲void *,因此您可以將所需的任何內容傳遞給該函數,包括指向this的指針。你的功能接受double,所以你不能通過this它。

我認爲最簡單的方法就是在課堂外定義中間函數,因爲它看起來獨立於類內部。類似這樣的:

double finte(double z) 
{ 
    return TFStolz(z, Zcglob); 
} 

您還可以將實例指針存儲在靜態函數可以讀取的公共全局/靜態in-class變量中。

+0

這似乎是一個簡單而乾淨的解決方案,但TFStolz是一個函數類DMSinv,所以如果當finte超出課堂時,它不會識別TFStolz:錯誤C3861:'TFStolz':標識符未找到。也許有些時候,包括TFStolz在內的指針......我不得不重新考慮它,因爲我說我是一個新手,不能輕鬆解決這個問題。謝謝! – madoro 2013-03-27 12:50:32