5 years, 2 months ago.

Initialization of NonCopyable object as a local variable in a class object

Hello Everyone,

I'm trying to get clear with RTOS functionality of MBED. Now I'm working with EventFlags class. I'm going to use this que-based object for tansport of events between my classes. For example, button pressed and whatever.

The problems is I don't know how to initialize a local variable in my own class. Let me explain:

main.cpp

EventFlags event_flags; // Init EventFlags
AVModule AVM=AVModule(); // Init my class
Thread tAVM; // Init thread for AVM
int main(){
 AVM.Init(event_flags); // Transfer EventFlags object to my object
 tAVM.start(callback(&AVM, &AVModule::Dispatcher)); //Assign a method of my class to the thread
 while(1){ // Main loop
   HAL_Delay(10000); // Just a pause
   event_flags.set(1);  // Drop a flag #1 to the que
  }
}

AVModule.cpp

AVModule::AVModule() { // Constructor of my object
}
AVModule::Init(EventFlags &ef){
EventFlags &_ef=ef;
}
void AVModule::Dispatcher(){
    uint32_t flags_read = 0;
    flags_read = _ef.wait_any(); // waiting for an event
}

AVModule.h

public:
void Dispatcher();
void Init(EventFlags &ef);
private:
EventFlags _ef;

So the question is how to init intra-class EventFlags variable that can be accessed by any of class members?

Currently I get tow error messages: 1. AVModule AVM=AVModule(); note: copy constructor of 'AVModule' is implicitly deleted because field '_ef' has a deleted copy constructor. That refers to main.cpp 2. EventFlags _ef; note: copy constructor of 'EventFlags' is implicitly deleted because base class 'mbed::NonCopyable<EventFlags>' has an inaccessible copy constructor class EventFlags : private mbed::NonCopyable<EventFlags> (that refers to AVModule.h)

1 Answer

5 years, 2 months ago.

Hello Vladislav,

The EventFlags class is an ancestor of the NonCopyable class. That was introduced in Mbed to prevent generation of copy constructor and copy assignment operator in order to prevent subtle bugs that are difficult to debug. So to avoid copying an instance of the EventFlags class like

_ef = ef;

which would call EventFlags's copy constructor, you have the following options:

  • Either declare the _ef data member as an EventFlags reference and initialize it in the constructor:

AVModule.h

class AVModule {
    EventFlags& _ef;
//...
public:
    AVModule(EventFlags& ef) : _ef(ef)  { }
//...
};

main.cpp

EventFlags  event_flags;
AVModule    AVM(event_flags);   // Creates in initializes the AVM object

int main()
{
//...
}
  • or declare the _ef data member as pointer to EventFlags and initialize it in the constructor:

AVModule.h

class AVModule {
    EventFlags* _ef;
//...
public:
    AVModule(EventFlags* ef) : _ef(ef)  { }
//...
};

main.cpp

EventFlags  event_flags; 
AVModule    AVM(&event_flags);   // Creates in initializes the AVM object

int main()
{
//...
}
  • or declare the _ef data member as pointer to EventFlags and initialize it by calling an init method:

AVModule.h

class AVModule {
    EventFlags* _ef;
//...
public:
    AVModule() { }
    void init(EventFlags* ef) { _ef = ef; }  // Assignes pointer to pointer. No copy constructor is called.
//...
};

main.cpp

EventFlags  event_flags;
AVModule    AVM;  // Creates the AVM object.

int main()
{
    AVM.init(&event_flags);  // Initializes the AVM object.
//...
}

I noticed that you have tried to "declare + define" an AVModule object like:

AVModule AVM=AVModule(); // Init my class

Such code first creates a temporary AVModule object (when AVModule() is called). Then creates another AVModule object with name AVM by calling AVModule's default constructor. And finally assigns the temporary AVModule object to the AVM object by calling AVModule's copy constructor.

It's simpler and more efficient to do it like:

AVModule AVM;  // Creates in initializes the AVM object.

Accepted Answer

Thank you very much for your exact explanations! Will implement them.

I used Java and C# and use to use creation of an object with new predicate. C++ is a little more tricky in that way.

posted by Vladislav Kravchenko 01 Oct 2019