Search code examples
c++qtreference-countingqshareddata

QSharedData and inheritance


I'm trying to make a type system while using QSharedData. The idea is simple, there will be a number of different data types, each of which is going to be derived from the base abstract class. I want to use QSharedData to store the actual data in each of them, but each of the derived classes is going to have different data stored inside. I'm trying to make the most basic example now, and having some troubles.

Let's say these are my base pure virtual classes:

class cAbstractData: public QSharedData
{
public:
    cAbstractData(){ }
    virtual int type() = 0;
};

class cAbstractValue
{
public:
    cAbstractValue(){ }
    virtual int type() = 0;
protected:
    QSharedDataPointer<cAbstractData>data_;
};

Now let's say I want to make a class for representing a single value (as a minmalistic example that is). I'm deriving the cAtomicValue from the base value class, and I am also deriving a data class to hold the value:

class cAtomicData:public cAbstractData
{
public:
    cAtomicData() { value_ = 0; }
    int type(){ return 1; }
    QVariant value_;//the actual value
};

class cAtomicValue:public cAbstractValue
{
public:
    cAtomicValue() { 
        data_ = new cAtomicData;//creating the data object.
    }
    int type(){ return 1; }
};

Now at this stage it works just fine, and in the debugger I can see the right pointer type. But now I want to add a function for setting and getting the value, and I fail to understand how to do it. Let's take the setter as an example. To set the value, we must access the value_ member of cAtomicData class through the data_ member of the cAtomicValue class. However since the data_ holds a base-class pointer (cAbstractData), I'll have to cast it to the right type (cAtomicData) somehow. I tried doing this:

template<class T> void set( T value )
{
    static_cast<cAtomicData*>(data_.data())->value_ = value;
}

it obviously doesn't work, because it called detach() and tries to make a copy of the base class which it can't since the base class is pure virtual. Then I tried to cast the pointer itself:

static_cast<cAtomicData*>(data_)->value_ = value;

but I'm getting an invalid static_cast ... error.

How do I do it, and am I even doing it the right way fundamentally?


Solution

  • I don't see any way to achieve what you're attempting here. As you've discovered, QSharedDataPointer needs to be templated on the actual type it contains.

    You could make your base class a template, e.g.

    template<class T>
    class cAbstractValue
    {
    public:
        cAbstractValue(){ }
        virtual int type() = 0;
    protected:
        QSharedDataPointer<T> data_;
    };
    

    But I'm not sure I see what benefit you would get from that.