QSharedPointer Deleter
-
Hi everyone.
I have a little trouble with using QSharedPointer.I dont found solution nor in google nor at this forum, thereby I start new theme.
Problem:
I have class Cipher. Object of this class produced by Factory, and return to user wrapped in QSharedPointer. Only Factory may produce this object, and only QSharedPointer may delete them.
For this reason I declare class this way:
@
class Cipher : public QObject
{
friend class Factory;
friend class QSharedPointer;public:
...
protected:
Cipher()
{};
virtual ~Cipher()
{};
};
@But I get error during compilation, because destructor is protected.
Adding following declaration resolve this problem:
@template <class T> friend class QtSharedPointer::ExternalRefCount;@But QtSharedPointer::ExternalRefCount hide from user and cannot be found in documentation. Thereby this solution is dirty hack and cannot be used.
After that I found deleter parameter in QSharedPointer constructor. Unfortunatelly Assistant don have enought documentation. I was leaded by intuition :) I modify class:
@
class Cipher : public QObject
{
friend class QSharedPointer;public:
...
protected:static void myDeleter(Cipher *obj) { delete obj; } Cipher() {}; virtual ~Cipher() {};
};
@
And call in factory following constructor:
@QSharedPointer <Cipher>result(temporary, &Cipher::myDeleter)@
But I recieve the same error. Declaring myDeleter as public dont resolve problem.Then I start reading source code of QSharedPointer and find this function:
@static inline void deref(Data *d, T *value)
{
if (!d) return;
if (!d->strongref.deref()) {
if (!d->destroy())
delete value;
}
if (!d->weakref.deref())
delete d;
}@
Here Value is pointer to Cipher object. And deleter function is called in @d->destroy()@
So I decide that QSharedPointer can not work with private destructor.Finally I have some questions.
- Can I use QSharedPointer with classes with private destructor?
- How can I deny deleting Cipher object to everyone except QSharedPointer?
- Who have complete documentation about deleter?
4 Is this bug or feature?
-
bq. 2. How can I deny deleting Cipher object to everyone except QSharedPointer?
You can't. If someone holds a cipher object by it's base class pointer (QObject*) the he can delete it.
-
Since Cipher is a QObject, it will emit a destroyed() signal. If there is a possibility that the Cipher is being destroyed without your classes knowing about it, you should from my point of view be handling the destroyed() signal, rather than trying to prevent users from deleting the thing.
-
Using a QPOinter could help, as it goes to 0 if the object behind is deleted. Then you only have to handle pointer != 0.
-
[quote author="Gerolf" date="1307522156"]Using a QPOinter could help, as it goes to 0 if the object behind is deleted. Then you only have to handle pointer != 0.[/quote]
And since QPointer is deprecated since Qt 4.6, you should use QWeakPointer. It does exactly the same and is said to be slightly safer. -
[quote author="Gerolf" date="1307522156"]Using a QPOinter could help, as it goes to 0 if the object behind is deleted. Then you only have to handle pointer != 0.[/quote]
I will look at this class.
It is not important that Cipher is inherited from QObject. I can modify class and remove this inheritence. Sorry that I dont describe this. Of course user can remove Cipher with pointer to QObject class.
What about this classes:
@class Cipher
{
friend class Factory;public:
...
protected:
Cipher()
{}
virtual ~Cipher()
{}
};class Factory
{
public:
static QSharedPointer<Cipher> create()
{
return QSharedPointer<Cipher>(new Cipher);
}
};
@What I need add to this definition for guarantee that only QSharedPointer can destroy Cipher object. Without @template <class T> friend class QtSharedPointer::ExternalRefCount;@
I have some places in my project with seems trouble. Really I can kick out this check, but it is very interesting task, and I wand to find solution.