如何(重新)调用已初始化对象的构造函数?
我正在编写一些代码来检查特定的 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
通过使用
placement new
您可以重新调用构造函数:new (&midiIn) ofxMidiIn()
行将重新构造midiIn
通过调用ofxMidiIn
的构造函数来获取自己的内存区域。但是,如果ofxMidiIn
有指针,并且您已在前一个对象中为它们分配了内存,则这种方法会产生问题。你将会泄漏内存。不过,您可以显式调用析构函数,方法如下:Demo : http://ideone.com/OaUtw
无论如何,我相信更好并且干净的解决方案是将变量设置为指针:
然后使用
new
和delete
。当您下次执行new
时,必须删除以前的对象,方法如下:By using
placement new
you can re-call the constructor:The line
new (&midiIn) ofxMidiIn()
will re-constructmidiIn
in its own memory region, by calling the constructor ofofxMidiIn
. However, this approach will create problem ifofxMidiIn
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:Demo : http://ideone.com/OaUtw
Anyway, I believe that better and clean solution would be to make the variable as pointer as:
And then use
new
anddelete
. And when you donew
for the next time, must delete the previous object by writing as:您不应调用构造函数两次。它通常可能会导致未定义的行为和不可维护的代码。
相反,您只需将构造函数代码的内容复制到类成员函数中(可能是
private
),然后在需要时调用该函数。例如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.使用指针而不是实例成员
Use a pointer instead of an instance member
在不了解这个特定类的任何情况下,直接的解决方案似乎是分配。
如果
ofxMidi
不可分配,则以某种方式包装对象是合适的。在基本层面上,只需在指针内即可。Without knowing anything about this particular class, the immediate solution appears to be assigning.
If
ofxMidi
is not assignable, wrapping the object somehow is appropriate. At the basic level, simply within a pointer.当需要重新创建时,使用指向 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.
您没有看到更新的 midiIn 的原因是因为您实际上正在创建两个实例 - 一个本地变量和一个成员变量。 recheck() 中的本地副本正在隐藏成员变量。在这一点上,我建议你调高编译器的警告级别,这样你就不会在其他地方意外地被这个问题烧伤。
就我个人而言,我会将 midiIn 包装在 std::shared_ptr 中并重新初始化。像这样的东西:
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: