Search code examples
templatesabstract-classavr-gcc

Templated abstract class which implements some general methods


I use avr-gcc and in my project are three devices which are able to output characters (Bluetooth, LCD, serial port). So I wrote three classes which implement the method ClassName* write(const char c). Now my idea was to write an abstract class which has the virtual method ReturnType* write(const char c) and implements some other methods like ReturnType* write(const char* c) or ReturnType* writeInt(const int16_t i) etc.

So I came to this:

template <class ReturnType>
class OutDevice {
    public:
        virtual ~OutDevice();

        virtual ReturnType* write(const char c) = 0;

        ReturnType* write(const char * c) {
            while (*c) {
                write(*c++);
            }
            return this;
        }
};

But when I try to use this abstract class in one of my three normal classes, I got a weird error:

#include "OutDevice.h"

class Display : public OutDevice<Display> {
    private:
        void send(uint8_t control, uint8_t data) {
            //some stuff
        }

    public:
        Display* write(const char c) { //error:   initializing argument 1 of 'virtual Display* Display::write(char)' [-fpermissive]
            send(_BV(IOC2), c);
            return this;
        }

        Display* write(const uint8_t row, const uint8_t column, const char* text) {
            setCursorPos(row, column);
            write(text); //error: invalid conversion from 'const char*' to 'char' [-fpermissive]
            return this;
        }
};

On line 10 I got this error:

error: initializing argument 1 of 'virtual Display* Display::write(char)' [-fpermissive]

What is the best way to do what I want or what am I doing wrong?

Thank you!

Edit: Added an extra method and the error avr-gcc gives me.


Solution

  • You declared the argument as const char:

    Display* write(const char c) 
    

    This is probably a mistake, since the base class method takes a const char* instead:

    ReturnType* write(const char * c)
    

    This mismatch leads to an error when you try to call the method with a const char* argument.


    Even if it's not a mistake, the effect is the same. The declaration of a write() function hides the declarations of any overloads from the base class. So the overwritten function is the one the compiler tries to call, other base class methods are not considered.

    To bring the other overloaded functions from the base class "into scope", add a using declaration to the derived class:

    using OutDevice::write;
    

    With this, the correct overload should be called.