Pass class instance to another class

Hi all.

Looking for some help with a C++ library i'm writing...

Let me outline the library structure:

I have an abstract class named BaseSettingsManager.
My BroadcastSettingsManager class is derived from BaseSettingsManager.
And within my sketch i have a global instance of BroadcastSettingsManager.

I have another abstract class named BaseBroadcastJob.
And i have two classes that are derived from BaseBroadcastJob: SyncBroadcastJob and TriggerBroadcastJob.

In my sketch i want to periodically create an instance of SyncBroadcastJob or TriggerBroadcastJob and pass this instance to a method of my BroadcastSettingsManager.

In BroadcastSettingsManager.h i have:

class BroadcastSettingsManager : public BaseSettingsManager{
public:
	BaseBroadcastJob* getBroadcastJob();
	void setBroadcastJob(BaseBroadcastJob *baseBroadcastJob);

protected:

	void loadAllParameters();
	void saveAllParameters();

private:

	BaseBroadcastJob *mBaseBroadcastJob=NULL;
};

And BroadcastSettingsManager.cpp:

BaseBroadcastJob* BroadcastSettingsManager::getBroadcastJob(){
	return mBaseBroadcastJob;
}

void BroadcastSettingsManager::setBroadcastJob(BaseBroadcastJob *baseBroadcastJob){
	mBaseBroadcastJob=baseBroadcastJob;
}

In my sketch, in in my Wire.onReceive() function:

  byte rfmCommand = Wire.read();
  switch (rfmCommand) {
    case REST_COMMAND_CODE_SET_SYNC_DATA: {
        SerializableSyncParameters serializableSyncParameters;
        byteCount--;
        for (byte i = 0; i < byteCount; i++) {
          serializableSyncParameters.Bytes[i] = Wire.read();
        }
        SyncBroadcastJob syncBroadcastJob(serializableSyncParameters);
        broadcastSettingsManager.setBroadcastJob(&syncBroadcastJob);
        lastCommandStatus = RESPONSE_CHAR_SUCCESS;
        break;
      }
    case REST_COMMAND_CODE_SET_TRIGGER_DATA: {
        SerializableTriggerParameters serializableTriggerParameters;
        byteCount--;
        for (byte i = 0; i < byteCount; i++) {
          serializableTriggerParameters.Bytes[i] = Wire.read();
        }
        TriggerBroadcastJob triggerBroadcastJob(serializableTriggerParameters);
        broadcastSettingsManager.setBroadcastJob(&triggerBroadcastJob);
        lastCommandStatus = RESPONSE_CHAR_SUCCESS;
        break;
      }
    default:
      lastCommandStatus = RESPONSE_CHAR_FAILURE
  }

And in my sketch's loop() function:

  BaseBroadcastJob *baseBroadcastJob = broadcastSettingsManager.getBroadcastJob();
  if (baseBroadcastJob != NULL && baseBroadcastJob->isEnabled()) {
    Serial.println("trying to broadcast");
    baseBroadcastJob->broadcast(rfmRadio);
  }
  delay(1000);

I have an RFM73 FSK radio module attached via SPI.
Passing an instance of BaseBroadcastJob to BroadcastSettingsManager's setBroadcastJob() method should cause the RFM73 to start making timed broadcasts based on the job's parameters.

Passing an instance of TriggerBroadcastJob causes a 'few' broadcasts - maybe 10 broadcasts - then the broadcasts cease.
The serial monitor repeatedly still shows "trying to broadcast".

Passing an instance of SyncBroadcastJob causes no broadcasts whatsoever and looking at the serial monitor i see that the arduino has restarted itself - it's crashed!

I'm guessing that the instance of TriggerBroadcastJob or SyncBroadcastJob created in Wire.onReceive() has been garbage collected and no longer exists.
My pointer mBaseBroadcastJob in BroadcastSettingsManager no longer points to the original instance - the sketch may crash or simply fail to make any broadcasts.

I'm new to OOP C++ but have experience with OOP java and am stuck.

How can i create instances of my TriggerBroadcastJob and SyncBroadcastJob classes locally in the Wire.onReceive() callback and pass them to my BroadcastSettingsManager?

I've Google a while but found nothing that works.
I also tried moving creation of the TriggerBroadcastJob and SyncBroadcastJob instances to the BroadcastSettingsManager class hoping that within BroadcastSettingsManager i could keep the instances in scope.
Neither of these attempts have worked:

void BroadcastSettingsManager::createBroadcastJob(SerializableSyncParameters serializableSyncParameters){
	delete mBaseBroadcastJob;
	mBaseBroadcastJob=new SyncBroadcastJob(serializableSyncParameters);
}

void BroadcastSettingsManager::createBroadcastJob(SerializableTriggerParameters serializableTriggerParameters){
	delete mBaseBroadcastJob;
	TriggerBroadcastJob *triggerBroadcastJob=new TriggerBroadcastJob(serializableTriggerParameters);
	mBaseBroadcastJob=triggerBroadcastJob;
}

The project fails to compile with either or both of these new methods.
Obscure errors about protected constructor and "error: within this context delete mBaseBroadcastJob;"

I can post more complete code if required but haven't done so in this post as there's an awful lot to post!

Any ideas anyone?

Thanks.

Martin.

Hi!

Why don't declare SyncBroadcastJob syncBroadcastJob and TriggerBroadcastJob triggerBroadcastJob as global classes? And you can make a function to assign locally the (serializableTriggerParameters) to the class.

The classes will change before you can use them in functions?

I'm guessing that the instance of TriggerBroadcastJob or SyncBroadcastJob created in Wire.onReceive() has been garbage collected

C++ doesn't have garbage collection (unless your code is a collection of garbage).

and no longer exists.

It has gone out of scope, so it no longer exists. But that is not garbage collection.

You need to use the new operator to allocate memory on the heap, so that the instance persists. The new operator returns a pointer to the allocated memory, so it needs to be stored in a pointer variable. You need to delete the instance when you are done with it, to release the memory.

giova014:
Why don't declare

SyncBroadcastJob syncBroadcastJob

and

TriggerBroadcastJob triggerBroadcastJob

as global classes? And you can make a function to assign locally the (serializableTriggerParameters) to the class.

That's an idea but surely the point of OOP is that i can reference a derived class as it's parent class?
It'd also involve keeping track of 2 pointers - not really a problem i suppose.
But i shall be creating more classes that are derived from my BaseBroadcastJob and don't want to create and manage a pointer for each derived class.

PaulS:
You need to use the new operator to allocate memory on the heap, so that the instance persists. The new operator returns a pointer to the allocated memory, so it needs to be stored in a pointer variable. You need to delete the instance when you are done with it, to release the memory.

I had attempted to do this - my original post shows how i'd tried - but didn't understand all the compiler errors the arduino IDE was showing.
Anyway i spent some time on it and it is now working... 8)
I have a single pointer in my library that points to an instance of one of my BaseBroadcastJob derived classes which is created in the library using the new keyword.
I delete any existing instance before creating a new one and have also implemented a destructor which too deletes any instance.

The compiler errors i mentioned were due to the fact that my BaseBroadcastJob and BaseSettingsManager classes both had virtual protected destructors i think.
Implementing public desctructors was the solution.

Thanks for both the replies.