How to override methods when inheriting from a class that uses templates?

Viewed 95

I'm having trouble trying to figure out how to properly write a class that both inherits from a class that uses templates and also overrides a virtual method. When I attempt to create an instance of this class, Visual Studio is giving me an error saying that

object of abstract type PropertyReal is not allowed: 
pure virtual function "Property<T>::propertyId [width t=qreal]" has no overrider

This is my code

template <typename T>
class Property
{
    T  _value;

public:
    Property(T initValue);
    ~Property();

    virtual QString propertyId() = 0;

    virtual T value() { return _value; }
    virtual void setValue(T value) { _value = value; }
};


template<typename T> 
Property::Property(T initValue)
    :_value(initValue)
{
}


template<typename T> 
Property::~Property()
{
}




class PropertyReal : public Property<qreal>
{
    static const QString ID;

public:
    PropertyReal();
    ~PropertyReal();

    template <qreal>
    QString propertyId() { return ID; }
};

const QString PropertyReal::ID = "real";

PropertyReal::PropertyReal()
{
}

PropertyReal::~PropertyReal()
{
}



class RectComp : Component
{
public:
    static const QString ID;

    PropertyReal _width;

public:
    RectComp();
    ~RectComp();

    QString componentId() { return ID;  }
};

The error is occurring when I declare the field PropertyReal _width. How would I fix this?

3 Answers

Try deleting the template <qreal> part.

Write simply

QString propertyId() { return ID; }

The point is that virtual ant template methods doesn't match. You can't make a virtual template method and a template method can't override a virtual class.

For other virtual methods

virtual T value() { return _value; }
virtual void setValue(T value) { _value = value; }

that are depending from the template T parameter of the Property class, you have to match the template parameter you have passed to the base class.

I mean... because PropertyReal inherit from Property<qreal>, you can override value() and setValue() as follows

qreal value () { /* something */ }
void setValue (qreal value) { /* something */ }

Like this:

class PropertyReal : public Property<qreal>
{
    static const QString ID;

public:
    PropertyReal();
    ~PropertyReal();

    // note: this is not a template!
    QString propertyId() override { return ID; }
};

override keyword is not necessary, but adding it is a good practice.

In your example Property is not a class, but a class template. You're deriving PropertyReal from an (implicitly) instantiated class Property<qreal> - when you used T in Property, you should use qreal in PropertyReal.

QString propertyId() override { return ID; }

should work just fine.

See simplified example: ideone

Related