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
    – KIIV
    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
    – KIIV
    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;
};
2

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.