1

Here's a small problem I encountered while I was trying to make this small header file Devices.h:

Is it possible to use templates with abstract classes ? If yes, how and how can I use that abstract class to derive another class ?

Here's the contents of the header file :

#ifndef Devices_h
#define Devices_h

/* Initial build for MCUOS 
Anybody can edit this according to their device needs */ 

#include "Arduino.h"

template < typename datatype>

class Device_Handler 
{
    // a class to handle devices
    public:
        virtual void write_to_device(datatype *send_data)= 0; // write data to device
        virtual void read_from_device(datatype *store_location)= 0 ; // read data from device to location
        virtual void clear_device() = 0; // clear device state
};

class Serial_Handler:public Device_Handler<char*>
{
   public:
          void write_to_device(char *send_data);
          void read_from_device(char *store_location);
          void clear_device();
};


void Serial_Handler<char*>::write_to_device(char *send_data){
        Serial.println(*send_data);
 }

void Serial_Handler<char*>::read_from_device(char *store_location){
       *store_location = Serial.read();
}

void Serial_Handler::clear_device(){
        Serial.flush(); 
}


#endif

This is a small project I am trying at home nowadays (that MCUOS thing up there😅), also considering it a learning opportunity. I am not sure if I wrote the code in the header the right way. Initially, I made the Device_Handler class and used it in my sketch to craft the Serial_Handler class, but then it showed an error that the compiler expected a class name before the '{' character right at the place where I started writing the code for the derived class. Thus I decided to move the code for the derived class to the header, but I decided to seek your advice before heading further as I fear that more errors may come up and as I am kind of a beginner at C++.

Thanks in advance !

EDIT : I also doubt if it was because I wrote a comment near the starting line of the abstract class as the syntax highlighter here showed the comments in colour.

Edit: I resolved the issue up there (it was due to the misplaced comment), but a new issue has popped up saying that it expected an initialiser before the '<' token at the places where I had defined the functions in the derived class. This is where my actual is.

My snippets of main concern:

void Serial_Handler<char>::write_to_device(char *send_data){
        Serial.println(*send_data);
 }

void Serial_Handler<char*>::read_from_device(char *store_location){
       *store_location = Serial.read();
}

I doubt if these will be able to handle long sentences or have syntax errors.

Edit I decided to move forward despite errors. Here's how I remade my header file:

#ifndef Devices_h
#define Devices_h

/* Initial build for MCUOS 
Anybody can edit this according to their device needs */ 

#include "Arduino.h"

template < typename datatype>
class Device_Handler 
{
               // a class to handle devices
    public:
        virtual void write_to_device(datatype *send_data)= 0; // write data to device
        virtual void read_from_device(datatype *store_location)= 0 ; // read data from device to location
        virtual void clear_device() = 0; // clear device state
};

class Serial_Handler:public Device_Handler<char*>
{
   public:
          void write_to_device(char *send_data);
          void read_from_device(char *store_location);
          void clear_device();
};


void Serial_Handler::write_to_device(char *send_data){
        Serial.println(*send_data);
 }

void Serial_Handler::read_from_device(char *store_location){
       *store_location = Serial.read();
}

void  Serial_Handler::clear_device(){
        Serial.flush(); 
}


#endif

Here's the sketch code:

#include <Devices.h>

Serial_Handler myserial;
char storage = '\0';
char test_string[] = "Hello";

void setup() {
  Serial.begin(9600);
  myserial.write_to_device(test_string);
  myserial.read_from_device(&storage);
}

void loop() {
  // put your main code here, to run repeatedly:

}

(I know that the code up there may also be faulty) and errors come up:

Arduino: 1.8.13 (Windows 10), Board: "Arduino Uno"
Devices_Test:3:16: error: cannot declare variable 'myserial' to be of abstract type 'Serial_Handler'

 Serial_Handler myserial;

                ^~~~~~~~

In file included from C:\Users\<smbdy>\Documents\Arduino\Devices_Test\Devices_Test.ino:1:0:

C:\Users\<smbdy>\Documents\Arduino\libraries\Devices/Devices.h:19:7: note:   because the following virtual functions are pure within 'Serial_Handler':

 class Serial_Handler:public Device_Handler<char*>

       ^~~~~~~~~~~~~~

C:\Users\<smbdy>\Documents\Arduino\libraries\Devices/Devices.h:14:16: note:     void Device_Handler<datatype>::write_to_device(datatype*) [with datatype = char*]

   virtual void write_to_device(datatype *send_data)= 0; // write data to device

                ^~~~~~~~~~~~~~~

C:\Users\<smbdy>\Documents\Arduino\libraries\Devices/Devices.h:15:16: note:     void Device_Handler<datatype>::read_from_device(datatype*) [with datatype = char*]

   virtual void read_from_device(datatype *store_location)= 0 ; // read data from device to location

                ^~~~~~~~~~~~~~~~

exit status 1

cannot declare variable 'myserial' to be of abstract type 'Serial_Handler'

How should I resolve this?

9
  • The Serial_Handler is not a template, so you are not supposed to be using SerialHandler <...> ::write_to_device / read from device Commented Apr 22, 2021 at 14:01
  • I edited it. Thanks @KIIV Commented Apr 22, 2021 at 14:05
  • Now I have run into another problem. Commented Apr 22, 2021 at 14:05
  • I defined the derived class definitions for the virtual functions is Device_Handler class but still the error came up... that is what is bothering me now. Commented Apr 22, 2021 at 14:11
  • 1
    The datatype is char*, that results into char ** send_data etc. But don't worry, I didn't noticed this one much sooner Commented Apr 22, 2021 at 14:14

1 Answer 1

1

You are on the track, but it needs some adjustments:

template < typename datatype>
class Device_Handler 
{
    // a class to handle devices
    public:
        virtual void write_to_device(datatype *send_data)= 0; // write data to device
        virtual void read_from_device(datatype *store_location)= 0 ; // read data from device to location
        virtual void clear_device() = 0; // clear device state
};

class Serial_Handler:public Device_Handler<char> // instead of char*
{
   public:
       void write_to_device(char *send_data) override;
       void read_from_device(char *store_location) override;
       void clear_device() override;
};

void Serial_Handler::write_to_device(char *send_data){ // It's not template, so no template specialization
        Serial.println(*send_data);
 }

void Serial_Handler::read_from_device(char *store_location){
       *store_location = Serial.read();
}

void Serial_Handler::clear_device(){
        Serial.flush(); 
}

The alternative is:

template < typename datatype>
class Device_Handler 
{
    // a class to handle devices
    public:
        virtual void write_to_device(datatype send_data)= 0; // write data to device
        virtual void read_from_device(datatype store_location)= 0 ; // read data from device to location
        virtual void clear_device() = 0; // clear device state
};

class Serial_Handler:public Device_Handler<char*>
{
   public:
       void write_to_device(char *send_data) override;
       void read_from_device(char *store_location) override;
       void clear_device() override;
};
1

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.