2011-07-29 124 views
3

我正在寫一些代碼,檢查是否插入了特定的MIDI設備,並且如果它不是代碼,則每5秒重新檢查一次,直到它插入。如何(重新)調用初始化對象的構造函數?

我的問題出現在檢查列表中的設備 - 外部庫沒有重新檢查端口的功能,因爲它只在類的構造函數中執行。

我可以看到讓我的代碼重新檢查設備列表的唯一方法是重新初始化類對象。

類對象在頭文件中聲明爲ofxMidiIn midiIn;,因爲它在cpp文件中被全局使用。問題是如果我在cpp中的函數中重新聲明,它看起來並沒有替換全局範圍中的對象,即使它本地很好。

要使用僞澄清:

在.H:

class foo { 

    ofxMidiIn midiIn; //first initialization does a port scan 

}; 

中的.cpp:

void foo::setup(){ 
    midiIn.listPorts(); //if this fails the recheck is triggered every 5 secs 
} 


void foo::run(){ 
    //if setup failed then while (!recheck()); 
} 

bool foo::recheck(){ 

    ofxMidiIn midiIn; 
    midiIn.listPorts(); //this works in this (local) scope, but doesn't reassign midiIn globally 

} 
+0

我不明白你真正要問的是什麼,直到我看到答案;我認爲'midiIn.listPorts()'不是實際上「重新檢查端口」的部分,儘管名稱不同。當你將'midiIn'描述爲「類對象」時,我也感到困惑。你明白類定義數據類型,每個'foo'實例都有一個單獨的'midiIn',對嗎? –

回答

7

通過使用placement new您可以重新調用構造函數:

bool foo::recheck() 
{ 
    new (&midiIn) ofxMidiIn(); 
    midiIn.listPorts(); 
} 

new (&midiIn) ofxMidiIn()在自己的內存區域將重新構造midiIn,通過調用ofxMidiIn構造。但是,如果ofxMidiIn具有指針,並且您在前一個對象中爲它們分配了內存,則此方法會產生問題。你將會泄漏記憶。你可以調用析構函數明確不過,通過寫爲:

(&midiIn)->~ofxMidiIn(); //call the destructor explicitly 
    new (&midiIn) ofxMidiIn(); //then do this! 

演示:http://ideone.com/OaUtw


無論如何,我相信,更好的和乾淨的解決辦法是把這些變量作爲指針爲:

ofxMidiIn *midiIn; 

然後用newdelete。而當你下一次做new,必須爲寫刪除以前的對象:

bool foo::recheck() 
{ 
    delete midiIn; //must do this if it already has been allocated memory! 
    midiIn = new ofxMidiIn(); 
    midiIn->listPorts(); 
} 
+0

這很好用,謝謝! –

+0

在閱讀其他答案之後,我傾向於使用指針方法,因爲它似乎更安全的記憶方式 –

+0

@Zak:這就是我在我的解決方案中提出的建議。 – Nawaz

0

不應調用構造函數兩次。它可能經常導致未定義的行爲和不可維護的代碼。

只是將構造函數代碼的內容複製到類成員函數中(可能是private),然後在需要時調用該函數。例如

class foo { 
    void check() 
    { 
    // put constructor logic here 
    } 
public: 
    foo() 
    { 
    //... 
    check(); 
    } 
// now call 'check()` wherever you want 
}; 
+0

是的,這將是理想的解決方案,但我不能真正編輯該類,因爲它引用了一個核心框架 –

0

使用指針來ofxMidiIn和動態分配,當你需要重新創建。確保遵循三個規則或從boost :: noncopyable繼承。

1

使用指針,而不是一個實例成員

class foo { 

    ofxMidiIn* midiIn; 

}; 


foo::foo() 
{ 
    midiIn = new ofxMidiIn; 
} 

foo::~foo() 
{ 
    delete midiIn; 
} 

void foo::setup(){ 
    midiIn->listPorts(); //if this fails the recheck is triggered every 5 secs 
} 


void foo::run(){ 
    //if setup failed then while (!recheck()); 
} 

bool foo::recheck(){ 

    delete midiIn; 
    miniIn = new ofxMIdiIn; 

    midiIn->listPorts(); //this works in this (local) scope, but doesn't reassign midiIn globally 

} 
0

不知道這個特定類的話,就是立即解決似乎分配。

ofxMidi midiIn; 
void function() { 
    ofxMidi localMidi; 
    if(we_have_our_new_data) 
    midiIn = localMidi; 
} 

如果ofxMidi不可轉讓,以某種方式包裝對象是適當的。在基本層面,只需在指針內。

std::shared_ptr<ofxMidi> midiIn; 

void function() { 
    std::shared_ptr<ofxMidi> localMidi(new ofxMidi); 
    if(we_have_our_data) 
    midiIn = localMidi; 
} 
0

你沒有看到更新的midiIn的原因是因爲你實際上創建了兩個實例 - 一個本地變量和一個成員變量。 recheck()中的本地副本隱藏了成員變量。在這一點上,我建議你提高編譯器的警告級別,以免在別的地方被意外燒燬。

就個人而言,我會將midiIn包裝在std :: shared_ptr中並重新初始化。就像這樣:

#include <memory> 

class foo { 

std::shared_ptr<ofxMidiIn> midiIn; //first initialisation does a port scan 

foo() : midiIn(std::make_shared<ofxMidiIn>()){} //Constructor 

bool recheck(){ 

midiIn = std::make_shared<ofxMidiIn>(); //Will blow away the old midiIn and replace it with a new one. 
midiIn->listPorts(); 
} 

}; 
相關問題