我正在为ESP8266开发一个小类,我需要能够在同一个对象的另一个实例中保存对象的引用。运行代码时,我一直在获取异常。经过一些调试后,它看起来像是在对象仍在范围内时调用类析构函数。我很长时间没有使用过C ++,但这种行为似乎不对。
真的有两个问题。
我已经将代码缩减为一个显示问题的小程序。在下面的代码中,类'析构函数在'child'对象上调用,而它仍在范围内。我在代码中指出它实际上被调用了两次。
这是代码的输出:
Starting adding child to root Out of scope name=child adding child to root2 Out of scope name=child Done, both root and child should still be in scope
#include "Arduino.h"
class TestObject {
private:
char name[20];
TestObject* child;
public:
TestObject(const char* name);
virtual ~TestObject();
void setChild(TestObject h) ;
char *getName();
};
TestObject::TestObject(const char *name) {
child = (TestObject*)0;
strcpy(this->name,name);
}
TestObject::~TestObject() {
Serial.println("Out of scope name="+String(name));
}
char *TestObject::getName() {
return name;
}
void TestObject::setChild(TestObject h ) {
child = &h;
Serial.println("adding "+String(h.name)+" to "+String(name));
}
void setup() {
Serial.begin(115200);
delay(1000);
Serial.println("\nStarting");
TestObject root = TestObject("root");
TestObject child = TestObject("child");
root.setChild(child); // child destructor is called here but it should still be in scope
delay(1000);
TestObject root2 = TestObject("root2");
root2.setChild(child);// child destructor is called a second time here
Serial.println("Done, both root and child should still be in scope");
while(true) {
delay(10000);
}
}
TestObject::setChild
按值获取其参数,以便创建TestObject
的副本,由函数使用,然后销毁。这是你所看到的析构函数的来源。 setChild
也指向这个本地副本,因此child
中的TestObject
指针指的是一个被破坏的对象。
解决方案是通过引用传递参数:
void TestObject::setChild(TestObject &h)
在void setChild(TestObject h)中;您将成员的子指针设置为临时(参数)的地址。您可能想要传递引用void setChild(TestObject&h);但即便如此,子指针也无法延长对象的生命周期。