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

发布于 2024-11-26 22:13:52 字数 772 浏览 0 评论 0原文

我正在编写一些代码来检查特定的 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

}

I'm writing some code that is checking if a specific midi device is plugged in, and if it isn't the code rechecks every 5 seconds until it is plugged in.

My problem comes about in checking the list of devices - the external library has no function to re-check the ports, as it only does it in the constructor of the class.

The only way I could see of getting my code to recheck the list of devices is to re-initialize the class object.

The class object is declared in the header file as ofxMidiIn midiIn;, as it is used globally in the cpp file. The issue is if I 'redeclare' within a function in the cpp it doesn't appear to replace the object in the global scope, even though it is locally fine.

To clarify with pseudocode:

In the .h:

class foo {

    ofxMidiIn midiIn; //first initialization does a port scan

};

in the .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

}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

太阳公公是暖光 2024-12-03 22:13:52

通过使用 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!

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

By using placement new you can re-call the constructor:

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

The line new (&midiIn) ofxMidiIn() will re-construct midiIn in its own memory region, by calling the constructor of ofxMidiIn. However, this approach will create problem if ofxMidiIn has pointer(s), and you've allocated memory for them in the previous object. You will be leaking memory. You can call the destructor explicitly though, by writing as:

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

Demo : http://ideone.com/OaUtw


Anyway, I believe that better and clean solution would be to make the variable as pointer as:

ofxMidiIn *midiIn;

And then use new and delete. And when you do new for the next time, must delete the previous object by writing as:

bool foo::recheck()
{
    delete midiIn; //must do this if it already has been allocated memory!
    midiIn = new ofxMidiIn();
    midiIn->listPorts(); 
}
二智少女 2024-12-03 22:13:52

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

相反,您只需将构造函数代码的内容复制到类成员函数中(可能是 private),然后在需要时调用该函数。例如

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

You should not call constructor twice. It may often result in undefined behavior and unmaintainable code.

Rather you copy the content of the constructor code into a class member function only (may be a private) and then call that function when needed. e.g.

class foo {
  void check ()
  {
    // put constructor logic here
  }
public:
  foo ()
  {
    //...
    check();
  }
// now call 'check()` wherever you want
};
治碍 2024-12-03 22:13:52

使用指针而不是实例成员

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

}

Use a pointer instead of an instance member

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

}
愁以何悠 2024-12-03 22:13:52

在不了解这个特定类的任何情况下,直接的解决方案似乎是分配。

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;
}

Without knowing anything about this particular class, the immediate solution appears to be assigning.

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

If ofxMidi is not assignable, wrapping the object somehow is appropriate. At the basic level, simply within a pointer.

std::shared_ptr<ofxMidi> midiIn;

void function() {
  std::shared_ptr<ofxMidi> localMidi(new ofxMidi);
  if(we_have_our_data)
    midiIn = localMidi;
}
2024-12-03 22:13:52

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

Use a pointer to ofxMidiIn and dynamic allocation when you need to recreate. Make sure you follow the rule of three or inherit from boost::noncopyable.

马蹄踏│碎落叶 2024-12-03 22:13:52

您没有看到更新的 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(); 
}

};

The reason you're not seeing the updated midiIn is because you're actually creating two instances - one local and one member variable. The local copy in recheck() is shadowing the member variable. On this point, I recommend you crank up your compiler's warning level so that you don't accidentally get burned by this in other places.

Personally I would wrap midiIn in a std::shared_ptr and re-initialize that. Something like this:

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

};
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文