Hi,
I fail to make the destructor of my PIMPL-Private base class pure virtual like QObjectData does. Since I don't know which information about the PIMPL is relevant or not here comes the "full" test case. (Basically at this point mostly equal to Q_DECLARE_PRIVATE...)
First one is working:
#ifndef FOO_H
#define FOO_H
#include <QtCore>
#define MYXXX_DECLARE_PRIVATE(Class) \
inline Class##Private* d_myxxx_func() { return reinterpret_cast<Class##Private *>(d_myxxx_ptr); } \
inline const Class##Private* d_myxxx_func() const { return reinterpret_cast<const Class##Private *>(d_myxxx_ptr); } \
friend class Class##Private;
#define MYXXX_DISABLE_COPY(Class) \
Class(const Class &); \
Class &operator=(const Class &);
#define MYXXX_DECLARE_PUBLIC(Class) \
inline Class* q_myxxx_func() { return static_cast<Class *>(q_myxxx_ptr); } \
inline const Class* q_myxxx_func() const { return static_cast<const Class *>(q_myxxx_ptr); } \
friend class Class;
#define MYXXX_D(Class) Class##Private * const d = d_myxxx_func()
#define MYXXX_Q(Class) Class * const q = q_myxxx_func()
//
// Base classes
//
class MYXXXPrivateHolder;
class MYXXXPrivate
{
protected:
MYXXXPrivate(MYXXXPrivateHolder *p) : q_myxxx_ptr(p) {}
MYXXXPrivateHolder *q_myxxx_ptr;
public:
virtual ~MYXXXPrivate() {qWarning() << Q_FUNC_INFO;} // this is the line!
};
class MYXXXPrivateHolder
{
protected:
MYXXXPrivateHolder(MYXXXPrivate *p)
: d_myxxx_ptr(p) {}
~MYXXXPrivateHolder() {
delete d_myxxx_ptr;
}
MYXXXPrivate *d_myxxx_ptr;
};
//
// Use case
//
class FilePrivate;
class
File : public QObject,
public MYXXXPrivateHolder
{
Q_OBJECT
public:
~File() {
qWarning() << Q_FUNC_INFO;
}
private:
MYXXX_DECLARE_PRIVATE(File)
MYXXX_DISABLE_COPY(File)
};
class FilePrivate : public MYXXXPrivate
{
public:
FilePrivate(File *_file) : MYXXXPrivate(_file) {}
~FilePrivate() {
qWarning() << Q_FUNC_INFO;
}
private:
MYXXX_DECLARE_PUBLIC(File)
};
#endif
#ifndef FOO_H
#define FOO_H
#include <QtCore>
#define MYXXX_DECLARE_PRIVATE(Class) \
inline Class##Private* d_myxxx_func() { return reinterpret_cast<Class##Private *>(d_myxxx_ptr); } \
inline const Class##Private* d_myxxx_func() const { return reinterpret_cast<const Class##Private *>(d_myxxx_ptr); } \
friend class Class##Private;
#define MYXXX_DISABLE_COPY(Class) \
Class(const Class &); \
Class &operator=(const Class &);
#define MYXXX_DECLARE_PUBLIC(Class) \
inline Class* q_myxxx_func() { return static_cast<Class *>(q_myxxx_ptr); } \
inline const Class* q_myxxx_func() const { return static_cast<const Class *>(q_myxxx_ptr); } \
friend class Class;
#define MYXXX_D(Class) Class##Private * const d = d_myxxx_func()
#define MYXXX_Q(Class) Class * const q = q_myxxx_func()
//
// Base classes
//
class MYXXXPrivateHolder;
class MYXXXPrivate
{
protected:
MYXXXPrivate(MYXXXPrivateHolder *p) : q_myxxx_ptr(p) {}
MYXXXPrivateHolder *q_myxxx_ptr;
public:
virtual ~MYXXXPrivate() {qWarning() << Q_FUNC_INFO;} // this is the line!
};
class MYXXXPrivateHolder
{
protected:
MYXXXPrivateHolder(MYXXXPrivate *p)
: d_myxxx_ptr(p) {}
~MYXXXPrivateHolder() {
delete d_myxxx_ptr;
}
MYXXXPrivate *d_myxxx_ptr;
};
//
// Use case
//
class FilePrivate;
class File : public QObject, public MYXXXPrivateHolder
{
Q_OBJECT
public:
File(QObject *parent = 0);
~File() {
qWarning() << Q_FUNC_INFO;
}
private:
MYXXX_DECLARE_PRIVATE(File)
MYXXX_DISABLE_COPY(File)
};
class FilePrivate : public MYXXXPrivate
{
public:
FilePrivate(File *_file) : MYXXXPrivate(_file) {}
~FilePrivate() {
qWarning() << Q_FUNC_INFO;
}
private:
MYXXX_DECLARE_PUBLIC(File)
};
#endif
To copy to clipboard, switch view to plain text mode
#include "foo.h"
, MYXXXPrivateHolder(new FilePrivate(this)) {}
#include "foo.h"
File::File(QObject *parent)
: QObject(parent)
, MYXXXPrivateHolder(new FilePrivate(this)) {}
To copy to clipboard, switch view to plain text mode
#include "foo.h"
int main(int argc, char *argv[])
{
File f;
return 0;
}
#include "foo.h"
int main(int argc, char *argv[])
{
File f;
return 0;
}
To copy to clipboard, switch view to plain text mode
Well, that compiles and gives the expected result:
virtual File::~File()
virtual FilePrivate::~FilePrivate()
virtual MYXXXPrivate::~MYXXXPrivate()
virtual File::~File()
virtual FilePrivate::~FilePrivate()
virtual MYXXXPrivate::~MYXXXPrivate()
To copy to clipboard, switch view to plain text mode
But when I change the marked line to
virtual ~MYXXXPrivate() = 0;
virtual ~MYXXXPrivate() = 0;
To copy to clipboard, switch view to plain text mode
I get the compilation error
foo.o: In function `FilePrivate::~FilePrivate()':
make: Leaving directory `/data/dev/asp/testprojekt-build-desktop'
foo.cpp:(.text._ZN11FilePrivateD2Ev[_ZN11FilePrivateD5Ev]+0xeb): undefined reference to `MYXXXPrivate::~MYXXXPrivate()'
foo.cpp:(.text._ZN11FilePrivateD2Ev[_ZN11FilePrivateD5Ev]+0x1c7): undefined reference to `MYXXXPrivate::~MYXXXPrivate()'
foo.o: In function `FilePrivate::~FilePrivate()':
foo.cpp:(.text._ZN11FilePrivateD0Ev[_ZN11FilePrivateD5Ev]+0xeb): undefined reference to `MYXXXPrivate::~MYXXXPrivate()'
foo.cpp:(.text._ZN11FilePrivateD0Ev[_ZN11FilePrivateD5Ev]+0x1d7): undefined reference to `MYXXXPrivate::~MYXXXPrivate()'
collect2: ld returned 1 exit status
make: *** [testprojekt] Error 1
What do I not see???
Thanks
Bookmarks