I have a project for ESP32 (Vscode/platformIO) with this code working: BCls receives in its constructor a pointer to an instance of ACls and assign it to its private _a. So in main.cpp, I just create and instance of ACls, then inject a pointer to it into the constructor of BCls:
main.cpp
#include "ACls.h"
ACls aa;
#include "BCls.h"
BCls bb(aa);
void setup() {
bb.doSomething("hello");
}
BCls.h
#include "ACls.h"
class BCls {
public:
ACls *_a;
//ctors
BCls();
BCls(ACls *aa);
}
BCls.cpp
#include "BCls.h"
#include "ACls.h"
BCls::BCls() {
}
BCls::BCls(ACls *aa) {
_a = aa;
}
But now I need to modify it so that, if BCls does not receive in its constructor an ACls instance, it must instantiate it internally and assign it to _a. I tried this but it does not work (compiles ok but fails in runtime):
main.cpp
#include "BCls.h"
BCls bb;
void setup() {
bb.doSomething("hello");
}
BCls.h
class BCls {
public:
ACls *_a;
//ctors
BCls();
BCls(ACls *aa);
}
BCls.cpp
#include "ACls.h"
BCls::BCls() {
//how to instantiate here an object of class ACls and assign a pointer to it to BCls._a??
//I tried this but its not working:
ACls aTmp;
_a = &aTmp;
}
BCls::BCls(ACls *aa) {
_a = aa;
}
the exception is
rst:0x8 (TG1WDT_SYS_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:2
load:0x3fff0030,len:1284
load:0x40078000,len:12808
load:0x40080400,len:3032
entry 0x400805e4
So, how should this be done?
I will try to explain deeper why I want to do this: Lets say I have 3 classes:
And lets say both GpsCls and SensorCls, need to log some data on the sd card. and also the project's main file needs to use the sd card to read files or whatever.
So right now, in projects main file, I instantiate SdCls, then instantiate GpsCls and SensorCls, passing the SdCls instance to their constructors. so now I can use the SD card in the projects main file, and both the gpsCls and SensorCls can use that same instance of SdCls to do their things. And everyone is happy.
But now I want these classes to be reusable in other projects. and lets say in another project, the only one that needs to access the SD card is the GpsCls. My idea with this was that, instead of instantiating the SdCls in the project main file, that I could just create the GpsCls object calling its empty constructor, and then let the GpsCls class instantiate the SdCls object it needs (as it will only be used by GpsCls)
I hope this is clearer now...
The problem you are facing is a result of the lifetime of the ACls
object you want to keep a pointer to in BCls
, by declaring it in the constructor, when the constructor returns, aTmp
goes out of scope and is destroyed and the pointer saved no longer points to a valid ACls
object.
There are a few options to solve this:
ACls
for every BCls
object, simply create a member ACls
:class BCls {
ACls _m_a;
ACls *_a;
public:
BCls() : _a(&_m_a) { }
BCls(ACls *aa) : _a(aa) { }
};
BCls
or they can share ACls
object, you can declare the aTmp
as static
:class BCls {
ACls *_a;
public:
BCls() {
static ACls aTmp; // Note this will be shared for all BCls objects that use this constructor
_a = &aTmp;
}
BCls(ACls *aa) : _a(aa) { }
};
ACls
(or you could allocate from a static pool but that involves more work that might not be worth it on something like an ESP32; also remember to delete the object in the destructor for the BCls
object if needed to not leak memory):class BCls {
ACls *_a;
public:
BCls() {
_a = new ACls();
}
BCls(ACls *aa) : _a(aa) { }
};