Help required with inheritance

Hello everyone,

I am making a subclass of the LiquidCrystal class which comes in the standard Arduino library. This subclass inherits everything from the parent class and adds 4 additional functions.
This is the first time I am doing something like this and can’t find any online material with instructions on how to do this. I keep running in to issues.

The superclass has many constructors with different parameters passed in, but I only want to use/override one of them. Is this possible?

The error I am receiving is:

C:\Arduino\libraries\LCDscreen\LCDscreen.cpp: In constructor 'LCDscreen::LCDscreen(uint8_t, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t)':
C:\Arduino\libraries\LCDscreen\LCDscreen.cpp:15: error: no matching function for call to 'LiquidCrystal::LiquidCrystal()'
C:\Arduino\libraries\LiquidCrystal440/LiquidCrystal.h:69: note: candidates are: LiquidCrystal::LiquidCrystal(uint8_t, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t, void (*)(int8_t))
C:\Arduino\libraries\LiquidCrystal440/LiquidCrystal.h:67: note:                 LiquidCrystal::LiquidCrystal(uint8_t, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t)
C:\Arduino\libraries\LiquidCrystal440/LiquidCrystal.h:65: note:                 LiquidCrystal::LiquidCrystal(uint8_t, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t, void (*)(int8_t))
C:\Arduino\libraries\LiquidCrystal440/LiquidCrystal.h:63: note:                 LiquidCrystal::LiquidCrystal(uint8_t, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t)
C:\Arduino\libraries\LiquidCrystal440/LiquidCrystal.h:61: note:                 LiquidCrystal::LiquidCrystal(uint8_t, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t)
C:\Arduino\libraries\LiquidCrystal440/LiquidCrystal.h:59: note:                 LiquidCrystal::LiquidCrystal(uint8_t, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t)
C:\Arduino\libraries\LiquidCrystal440/LiquidCrystal.h:56: note:                 LiquidCrystal::LiquidCrystal(uint8_t, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t)
C:\Arduino\libraries\LiquidCrystal440/LiquidCrystal.h:52: note:                 LiquidCrystal::LiquidCrystal(const LiquidCrystal&)

LiquidCrystal.h and LiquidCrystal.cpp are in the .zip file attached (too large to paste them in here). No changes were made to the standard LiquidCrystal library.

Below is the subclass code I’ve created:

LCDscreen.h

#ifndef LCDscreen_h
#define LCDscreen_h

#include <LiquidCrystal.h>

class LCDscreen : public LiquidCrystal
{
  public:
	LCDscreen(uint8_t, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t);
	void q1(String);
	void q2(String);
	void q3(String);
	void q4(String);
	
  private:
	String strContent;
	char charBuf[];
	String newString;
	int i;	
};

#endif

LCDscreen.cpp

#include "LCDscreen.h"
#include <LiquidCrystal.h>

LCDscreen::LCDscreen(uint8_t rs, uint8_t rw, uint8_t enable, uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3) {
	// Add code here
}

void LCDscreen::q1(String strContent) {

}

void LCDscreen::q2(String strContent) {

}

void LCDscreen::q3(String strContent) {

}

void LCDscreen::q4(String strContent) {

}

Arduino code:

#include <LiquidCrystal.h>
#include "LCDscreen.h"
#include <Wire.h>

LCDscreen lcd = LCDscreen(12, 11, 10, 5, 4, 3, 2); // Pins used for LCD screen

void setup ()
  {
  Serial.begin (115200);

  }  // end of setup

void loop () { }

Any help you could offer would be greatly appreciated.
Many thanks.

LiquidCrystal440.zip (6.84 KB)

You can attach files,including zip files, which means all these bits and pieces are not necessary.

How to use this forum

[quote author=Nick Gammon link=topic=187762.msg1389618#msg1389618 date=1379051628] You can attach files,including zip files, which means all these bits and pieces are not necessary.

How to use this forum

[/quote]

Understood. I will edit the post and attach the files.

Could anyone help me with this please?

Since you're not specifying what superclass' constructor candidate to use, it's assuming you want a zero argument one. Problem is the LiquidCrystal class doesn't have a zero argument constructor. Change this:

LCDscreen::LCDscreen(uint8_t rs, uint8_t rw, uint8_t enable, uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3)

to this:

LCDscreen::LCDscreen(uint8_t rs, uint8_t rw, uint8_t enable, uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3) : LiquidCrystal(rs, rw, enable, d0, d1, d2, d3)

When you inherit a class you don't get any copies of the constructors, nor are any "overloaded" constructors created for you - with the exception of two "standard" constructors - one with no arguments, and a "copy" constructor (one which just takes a class instance as an argument).

You select which superclass constructors to call by calling them explicitly. This is usually done in an initialization list:

class myClass : public parentClass {
  public:
    myClass(...my args...) : parentClass(...args to pass on...);
};

For example, you can set some static values to use by using literals in the argument list, or by specifying default values for parameters:

class myClass : public parentClass {
  public:
    myClass(int a, int b, int c = 10) : parentClass(b, 3, c);
};

Thanks very much guys! Makes perfect sense. I will give this a go tomorrow when I am back home and report in :) Thanks again :)

OK… FINALLY got a chance to test this! (wife and I are expecting soon, so not much time on our hands these days as we prepare).

I’ve made the suggested changes, but now I get this error.

In file included from sketch_sep20b.ino:2:
C:\Arduino\LCDscreen/LCDscreen.h: In constructor 'LCDscreen::LCDscreen(uint8_t, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t)':
C:\Arduino\LCDscreen/LCDscreen.h:9: error: expected `{' at end of input

I’ve search the net and the forums for the same error but cant find it. Ive also tried putting a { in various places but to no affect.

So my code now is:
LCDscreen.cpp

#include "LCDscreen.h"
#include <LiquidCrystal.h>

LCDscreen::LCDscreen(uint8_t rs, uint8_t rw, uint8_t enable, uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3) : LiquidCrystal(rs, rw, enable, d0, d1, d2, d3) {
// Tested with the below line, but it still didnt work
// LCDscreen::LCDscreen(uint8_t rs, uint8_t rw, uint8_t enable, uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3) {
}

LCDscreen.h

#ifndef LCDscreen_h
#define LCDscreen_h

#include <LiquidCrystal.h>

class LCDscreen : public LiquidCrystal
{
  public:
	LCDscreen(uint8_t rs, uint8_t rw, uint8_t enable, uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3) : LiquidCrystal(rs, rw, enable, d0, d1, d2, d3);
	// Tested with the below line, but it didnt work
	// LCDscreen(uint8_t rs, uint8_t rw, uint8_t enable, uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3) : LiquidCrystal(1, 2, 3, 4, 5, 6, 7);
};
#endif

Arduino sketch code:

#include <LiquidCrystal.h>
#include "LCDscreen.h"
#include <Wire.h>

LCDscreen lcd = LCDscreen(12, 11, 10, 5, 4, 3, 2); // Pins used for LCD screen

void setup ()
  {
  Serial.begin (115200);

  }  // end of setup

void loop () { }

I’ve tried various combinations, adding and removing braces etc… but nothing is working. I am going insane trying to get something that should be relatively simple (or at least well documented by someone else who had the same problems somewhere on the interwebs) to work.

Thanks again for your continued help. Very much appreciated. You are doing your bit to stop little ol’ Jay from join absolutely bonkers! :slight_smile:

Specify only your constructor "signature" (ie. the name and argument datatypes) in the .h file. Your actual implementation of that constructor in the .cpp file is where you invoke the the superclass constructor using ":"

http://www.learncpp.com/cpp-tutorial/114-constructors-and-initialization-of-derived-classes/ has some basic info on base-derived class construction.

He's right. You are doing this twice:

: LiquidCrystal(rs, rw, enable, d0, d1, d2, d3)

OK, I tried the above code now that I found some time to work on this.
I looked through the tutorial that tttt supplied the link for above. But, most of it is double-dutch to me. My programming knowledge is limited and it really is on a ‘as-needed’ basis, considering this is a hobby for me and it isnt my actual vocation.
This is why I come to these forums to ask you helpful chaps for some assistance :slight_smile:
I looked around that site and although it seems great (ive bookmarked it for bedtime reading) I cant find how to fix this issue!
I hope I am not stretching the boundaries of our tenuous relationship here :slight_smile: Any help would be greatly appreciated.

So my error is different now that I made some errors which I found from the link that tttt supplied (thanks!).

Error

C:\ArduinoProjects\libraries\LCDscreen\LCDscreen.cpp:4: error: redefinition of 'LCDscreen::LCDscreen(uint8_t, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t)'
C:\ArduinoProjects\libraries\LCDscreen\/LCDscreen.h:9: error: 'LCDscreen::LCDscreen(uint8_t, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t)' previously defined here

LCDscreen.h

#ifndef LCDscreen_h
#define LCDscreen_h

#include <LiquidCrystal.h>

class LCDscreen : public LiquidCrystal
{
  public:
	LCDscreen(uint8_t rs, uint8_t rw, uint8_t enable, uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3) : LiquidCrystal(rs, rw, enable, d0, d1, d2, d3)
	{
	}
};
#endif

LCDscreen.cpp

#include "LCDscreen.h"
#include <LiquidCrystal.h>

LCDscreen::LCDscreen(uint8_t rs, uint8_t rw, uint8_t enable, uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3) {
}

Arduino code

#include <LiquidCrystal.h>
#include "LCDscreen.h"
#include <Wire.h>

LCDscreen lcd = LCDscreen(12, 11, 10, 5, 4, 3, 2); // Pins used for LCD screen
//LCDscreen lcd(12, 11, 10, 5, 4, 3, 2); // Pins used for LCD screen

void setup ()
  {
  Serial.begin (115200);

  }  // end of setup

void loop () { }

As always, thanks for your help.

  public:
    LCDscreen(uint8_t rs, uint8_t rw, uint8_t enable, uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3) : LiquidCrystal(rs, rw, enable, d0, d1, d2, d3)
    {
    }

Two problems here. First, you are implementing the method in the header file, which is wrong.

Second, there is no difference to the compiler between:

    LCDscreen(uint8_t rs, uint8_t rw, uint8_t enable, uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3);

and

    LCDscreen(uint8_t rs,
                            uint8_t rw,
                             uint8_t enable,
                             uint8_t d0,
                             uint8_t d1,
                             uint8_t d2,
                             uint8_t d3);

but there is to people. Use the carriage return appropriately.

PaulS, this is the way they did it in the tutorial that tttt posted (http://www.learncpp.com/cpp-tutorial/114-constructors-and-initialization-of-derived-classes/) so I am inclined to believe their method is correct. Also, I tried it without implementing the method and still got an error (albeit a different one), see my above post for that.

You can implement the method in the header file (but I don’t like that) OR in the source file. Make up your mind where you want to do it.

PaulS is right. See this:

{
}

You have that in the header and the .cpp file. Lose one of them.

jaykard: I am inclined to believe their method is correct.

The tutorial does it that way to avoid the distraction of having the implementation divided between .cpp and .h files. That does not mean it is a sensible or good way to implement production code. I suggest you stick to the conventional approach of putting your declarations in .h files and your definitions in .cpp files for your own code.

SUCCESS!

Finally got it working thanks to you gents.

So to close the loop on this thread and for posterity, below is my working code.

I tried to keep the declarations in .h and definitions in .cpp but I couldn’t get it working. I finally settled on the below which works for me. I would prefer to stick to convention, but when convention fails then ill stick to what works :slight_smile:

Arduino code:

#include <LiquidCrystal.h>
#include "LCDscreen.h"
#include <Wire.h>

LCDscreen lcd = LCDscreen(12, 11, 10, 5, 4, 3, 2); // Pins used for LCD screen
//LCDscreen lcd(12, 11, 10, 5, 4, 3, 2); // Pins used for LCD screen

void setup ()
  {
  Serial.begin (115200);

  }  // end of setup

void loop () { }

LCDscreen.cpp

#include "LCDscreen.h"
#include <LiquidCrystal.h>

LCDscreen::LCDscreen(uint8_t rs,
				uint8_t rw,
				uint8_t enable,
				uint8_t d0,
				uint8_t d1,
				uint8_t d2,
				uint8_t d3);

LCDscreen.h

#ifndef LCDscreen_h
#define LCDscreen_h

#include <LiquidCrystal.h>

class LCDscreen : public LiquidCrystal
{
  public:
	LCDscreen(uint8_t rs,
			uint8_t rw,
			uint8_t enable,
			uint8_t d0,
			uint8_t d1,
			uint8_t d2,
			uint8_t d3) : LiquidCrystal(rs,
						rw,
						enable,
						d0,
						d1,
						d2,
						d3)
							{
							}
};
#endif