QSharedData和继承

Sin*_*all 5 c++ qt reference-counting qshareddata

我正在尝试使用时使用类型系统QSharedData.这个想法很简单,会有许多不同的数据类型,每个类型都将从基础抽象类派生.我想用它QSharedData来存储每一个中的实际数据,但是每个派生类都会在里面存储不同的数据.我现在正试图做出最基本的例子,并遇到一些麻烦.

假设这些是我的基本纯虚拟类:

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

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

现在让我们说我想创建一个表示单个值的类(作为一个简单的例子).我cAtomicValue从基值类派生,我也派生一个数据类来保存值:

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; }
};
Run Code Online (Sandbox Code Playgroud)

现在在这个阶段它工作得很好,在调试器中我可以看到正确的指针类型.但现在我想添加一个设置和获取值的函数,我不明白该怎么做.我们以制定者为例.要设置值,我们必须访问value_的成员cAtomicData通过类data_的成员cAtomicValue类.但是由于data_保存了一个基类指针(cAbstractData),我必须以cAtomicData某种方式将它转换为正确的类型().我试过这样做:

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

它显然不起作用,因为它调用detach()并尝试制作它不能的基类的副本,因为基类是纯虚拟的.然后我试着投射指针本身:

static_cast<cAtomicData*>(data_)->value_ = value;
Run Code Online (Sandbox Code Playgroud)

但我收到了一个invalid static_cast ...错误.

我该怎么做,我是否从根本上以正确的方式做到了这一点?

Hel*_*bye 6

你可以切换到QExplicitlySharedDataPointer而不是QSharedDataPointer.detach()每当您尝试获取指向cAbstractData对象的非const指针时,都不会调用此方法,包括将QExplicitlySharedDataPointer<cAbstractData>对象强制转换为QExplicitlySharedDataPointer<cAtomicData>对象.但是,如果要使用copy-on-write detach(),cAbstractData则每次要对其进行修改时都需要手动调用.也许你可以编写一个包装类来为你执行分离.

此方法可能优先使用QSharedPointer,因为a QExplicitlySharedDataPointer与普通指针的大小相同(因此保持二进制兼容性),而a QSharedPointer的大小是两倍(参见此博客条目).

编辑:请注意,来自QExplicitlySharedDataPointer<cAbstractData>to 的强制转换QExplicitlySharedDataPointer<cAtomicData>是静态的,因此您必须保证实际引用的对象是该类型cAtomicData(或子类)的对象,或者使用指针时的行为可能是未定义的.


Dan*_*urn 2

我看不出有什么方法可以实现您在这里尝试的目标。正如您所发现的,QSharedDataPointer需要根据它包含的实际类型进行模板化。

您可以将基类设为模板,例如

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

但我不确定你会从中得到什么好处。