2011-07-29 142 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(); 
} 

}; 
相关问题