In C++, a class that holds reference members (in your sample, LiquidCrystal& _Clcd1;
and LiquidCrystal& _Clcd2;
) must ensure these references are initialized at construction time, not later.
This means your void init(LiquidCrystal& Clcd1, LiquidCrystal& Clcd2);
method is not the right way to initialize _Clcd1
and _Clcd2
because it will be called after construction time.
You have 2 ways to solve this issue,t hat I will detail further below.
HOWEVER, before we discuss the solutions, you must be aware that your sample code has a huge defect in setup()
method code!
void setup()
{
//LiquidCrystal lcd(RS,RW,Enable1,Enable2, data3,data2,data1,data0);
LiquidCrystal lcd(12, 11, 7, 6, 5, 4); //declare two LCD's
LiquidCrystal lcd2(12, 10, 7, 6, 5, 4); // Ths is the second
LCDController.init(lcd, lcd2);
}
Here, you create lcd
and lcd2
in your setup
method, but their life ends at the end of setup()
, because they have been allocated on the stack. Using these outside setup()
will most likely cause your program to crash as soon as your loop()
tries to access lcd
or lcd2
, indirectly through LCDController
method calls.
To remove this defect, you must declare these variables outside setup
:
//LiquidCrystal lcd(RS,RW,Enable1,Enable2, data3,data2,data1,data0);
LiquidCrystal lcd(12, 11, 7, 6, 5, 4); //declare two LCD's
LiquidCrystal lcd2(12, 10, 7, 6, 5, 4); // Ths is the second
void setup()
{
LCDController.init(lcd, lcd2);
}
Now you can use them anywhere in your program, you are sure they are present and "alive".
Now we can go to the solutions of the original compilation problem.
1. Initialize references at construction by adding a constructor
class LCDControllerClass
{
public:
LCDControllerClass(LiquidCrystal& Clcd1, LiquidCrystal& Clcd2)
: _Clcd1(Clcd1), _Clcd2(Clcd2) {}
...
};
You can still keep an void init()
method to complete the initialization if you don't want it to occur right at construction time, or you can fully integrate the current init()
content into the constructor and re,voe init()
altogether:
class LCDControllerClass
{
public:
LCDControllerClass(LiquidCrystal& Clcd1, LiquidCrystal& Clcd2)
: _Clcd1(Clcd1), _Clcd2(Clcd2)
{
_Clcd1.begin(40, 2);
_Clcd1.clear();
_Clcd2.begin(40, 2);
_Clcd2.clear();
}
...
};
In anycase, you will have to change the way you instantiate your LCDControllerClass LCDController
which you did not show in your sample code, that would be something like this:
LiquidCrystal lcd(...);
LiquidCrystal lcd2(...);
LCDControllerClass LCDController(lcd, lcd2);
That obviously requires that you can instantitate lcd
and lcd2
before creating LCDController
. If that is not possible for you, then you'll have to use the second way.
2. Replace references with pointers
As mentioned before, in a class reference members MUST be initialized at construction time (moreover, they cannot be changed afterwards, to point somewhere else). This is not the case for pointers however:
class LCDControllerClass
{
public:
void init(LiquidCrystal* Clcd1, LiquidCrystal* Clcd2);
private:
void _UpdateLCD(int iLine, int iPosition, String cText);
LiquidCrystal* _Clcd1;
LiquidCrystal* _Clcd2;
};
void LCDControllerClass::init(LiquidCrystal* Clcd1, LiquidCrystal* Clcd2)
{
_Clcd1 = Clcd1;
_Clcd1->begin(40, 2);
_Clcd1->clear();
_Clcd2 = Clcd2;
_Clcd2->begin(40, 2);
_Clcd2->clear();
}
Note that now, you need to use the arrow notation ->
to access _Clcd1
and _Clcd2
members (dot notation cannot work for pointers).
The rest of the code should be slightly modified to reflect this change:
//LiquidCrystal lcd(RS,RW,Enable1,Enable2, data3,data2,data1,data0);
LiquidCrystal lcd(12, 11, 7, 6, 5, 4); //declare two LCD's
LiquidCrystal lcd2(12, 10, 7, 6, 5, 4); // Ths is the second
void setup()
{
LCDController.init(&lcd, &lcd2);
}
Note that we now have to pass the address of lcd
and lcd2
to init()
, by using &
before their names.