如何(重新)调用初始化对象的构造函数?

时间:2011-07-29 03:34:04

标签: c++ constructor scope initialization

我正在编写一些代码,用于检查是否插入了特定的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

}

6 个答案:

答案 0 :(得分:10)

使用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(); 
}

答案 1 :(得分: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

}

答案 2 :(得分:0)

不应该两次调用构造函数。它可能经常导致未定义的行为和不可维护的代码。

而是将构造函数代码的内容仅复制到类成员函数中(可能是private),然后在需要时调用该函数。 e.g。

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

答案 3 :(得分:0)

在需要重新创建时,使用指向ofxMidiIn和动态分配的指针。确保遵循三级规则或从boost :: noncopyable继承。

答案 4 :(得分: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;
}

答案 5 :(得分:0)

您没有看到更新的midiIn的原因是因为您实际上正在创建两个实例 - 一个本地变量和一个成员变量。 recheck()中的本地副本正在遮蔽成员变量。在这一点上,我建议你提高你的编译器的警告级别,这样你就不会在其他地方意外地被它烧掉。

我个人会在std :: shared_ptr中包装midiIn并重新初始化它。像这样:

#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(); 
}

};