我有一个简单的抽象基类:
class Sensor {
protected:
GenericDriver *driver;
public:
Sensor() {};
virtual void startNewReadout(void) = 0;
};
从中派生出一个具体的类:
class OneWireSensor : public Sensor {
private:
OneWireDriver oneWireDriver; //not really necessary here
public:
OneWireSensor(PinData *pinData);
void startNewReadout(void){
this->driver->driverStartReadout();
}
};
现在,当我使用以下构造函数时,我的代码将按预期方式编译并运行:
OneWireSensor::OneWireSensor(PinData *pinData) : oneWireDriver(OneWireDriver(pinData)) {
this->driver = &oneWireDriver;
}
但是,字段oneWireDriver在我的代码中没有使用,并且我不想设置它。但是,当我从OneWireSensor类中删除它并使用如下构造函数:
OneWireSensor::OneWireSensor(PinData *pinData) {
OneWireDriver oneWireDriver(pinData);
this->driver = &oneWireDriver;
}
代码可以很好地编译但是执行会在运行时异常中结束(由于我是嵌入式系统,所以这是系统的硬错误)。 GenericDriver是OneWireDriver类继承的抽象类。在第二种情况下我怎么了?
该问题很可能是由于OneWireSensor
的构造函数中悬空的指针引起的。
OneWireSensor::OneWireSensor(PinData *pinData) {
// A function local object.
OneWireDriver oneWireDriver(pinData);
// Pointer to the function local object.
// It becomes a dangline pointer as soon as the function returns.
this->driver = &oneWireDriver;
}
您需要使用动态分配的对象。
OneWireSensor::OneWireSensor(PinData *pinData) {
this->driver = new OneWireDriver(pinData);
}
但是您必须编写代码来管理动态分配的内存。最好使用智能指针而不是原始指针。有关智能指针的更多信息,请参见https://en.cppreference.com/w/cpp/memory。
在问题情况下,oneWireDriver
仅在构造函数正在运行时存在,然后超出范围。使用任何指向它的指针都是未定义的行为。
您正在这里创建对象:
OneWireSensor::OneWireSensor(PinData *pinData) {
OneWireDriver oneWireDriver(pinData); //<<<------
this->driver = &oneWireDriver;
}
在功能范围内。然后,将其地址分配给该类的成员。
功能范围结束后,oneWireDriver
变量被销毁。现在,该类有了指向所有地方的迷人指针。在执行的某个时刻,您可能尝试取消引用它,从而导致RuntimeException。
您需要确保该函数结束后变量将继续存在。您可以在堆上分配它,需要记住在析构函数上进行分配。