在 Qt Pimpl class 中创建 Private subclass 时出现多重定义错误
Multiple definition error when creating Private subclass in Qt Pimpl class
我一直在尝试按照 this Qt wiki page 上的说明实现 Pimpl class,其中私有 class 继承自另一个私有基础 class。
这是一个基本示例:
基地class
页眉
// gadget.h
#ifndef GADGET_H
#define GADGET_H
#include <QWidget>
class GadgetPrivate;
class Gadget : public QWidget
{
Q_OBJECT
public:
explicit Gadget(QWidget *parent = 0);
~Gadget();
protected:
Gadget(GadgetPrivate &d, QWidget *parent = 0);
GadgetPrivate *d_ptr;
private:
Q_DISABLE_COPY(Gadget)
Q_DECLARE_PRIVATE(Gadget)
};
#endif // GADGET_H
实施
// gadget.cpp
#include "gadget.h"
#include "gadget_p.h"
Gadget::Gadget(QWidget *parent)
: QWidget(parent),
d_ptr(new GadgetPrivate(this))
{}
Gadget::~Gadget() {}
Gadget::Gadget(GadgetPrivate &d, QWidget *parent)
: QWidget(parent),
d_ptr(&d)
{}
私人class
// gadget_p.h
#ifndef GADGET_P_H
#define GADGET_P_H
#include "gadget.h"
class GadgetPrivate
{
Q_DECLARE_PUBLIC(Gadget)
public:
GadgetPrivate(Gadget *q);
Gadget *q_ptr;
};
GadgetPrivate::GadgetPrivate(Gadget *q)
: q_ptr(q)
{}
#endif // GADGET_P_H
亚class
页眉
// gizmo.h
#ifndef GIZMO_H
#define GIZMO_H
#include "gadget.h"
class GizmoPrivate;
class Gizmo : public Gadget
{
Q_OBJECT
public:
explicit Gizmo(QWidget *parent = 0);
~Gizmo();
private:
Q_DISABLE_COPY(Gizmo)
Q_DECLARE_PRIVATE(Gizmo)
};
#endif // GIZMO_H
实施
// gizmo.cpp
#include "gizmo.h"
#include "gadget_p.h"
class GizmoPrivate : public GadgetPrivate
{
Q_DECLARE_PUBLIC(Gizmo)
public:
GizmoPrivate(Gizmo *q);
};
GizmoPrivate::GizmoPrivate(Gizmo *q)
: GadgetPrivate(q)
{}
Gizmo::Gizmo(QWidget *parent)
: Gadget(*new GizmoPrivate(this), parent)
{}
Gizmo::~Gizmo() {}
我收到以下错误:
In function `GadgetPrivate::GadgetPrivate(Gadget*)':
error: multiple definition of `GadgetPrivate::GadgetPrivate(Gadget*)'
有谁知道我做错了什么吗?
这个构造函数声明:
Gadget(GadgetPrivate &d, QWidget *parent)
需要引用 GadgetPrivate
,此时它只是前向声明的 class。把参数类型换成指针就可以了:
Gadget(GadgetPrivate *d, QWidget *parent)
和:
Gadget(GadgetPrivate *d, QWidget *parent)
: QWidget(parent), d_ptr(d)
{}
一些注意事项:
- 首先,为您的
d_ptr
使用 QScopedPointer
。这将防止您因未删除 d_ptr
而造成的内存泄漏。 q_ptr
应该保持原始指针。
- This Q&A 关于 PIMPL 习语非常棒,包括很多关于 "gotcha" 等的提示。
- Marc Mutz 撰写了一些关于 Qt 和 pimpl idiom 的精彩文章。他们身价 checking out。我链接到文章的第 2 部分,因为它详细介绍了内部结构。
解决方案 #1:
使私有库中的所有内容 class 内联,即更改此设置,
class GadgetPrivate
{
Q_DECLARE_PUBLIC(Gadget)
public:
GadgetPrivate(Gadget *q);
Gadget *q_ptr;
};
GadgetPrivate::GadgetPrivate(Gadget *q)
: q_ptr(q)
{
}
到,
class GadgetPrivate
{
Q_DECLARE_PUBLIC(Gadget)
public:
GadgetPrivate(Gadget *q)
: q_ptr(q)
{
}
Gadget *q_ptr;
};
编译代码。
解决方案 #2:
这似乎也有效:
gadget_p.h
class GadgetPrivate
{
Q_DECLARE_PUBLIC(Gadget)
public:
GadgetPrivate(Gadget *q);
Gadget *q_ptr;
};
gadget.cpp
#include "gadget.h"
#include "gadget_p.h"
GadgetPrivate::GadgetPrivate(Gadget *q)
: q_ptr(q)
{
}
Gadget::Gadget(QWidget *parent)
: QWidget(parent),
d_ptr(new GadgetPrivate(this))
{
}
Gadget::~Gadget()
{
}
Gadget::Gadget(GadgetPrivate *d, QWidget *parent)
: QWidget(parent),
d_ptr(d)
{
}
GadgetPrivate
的实施已移至 gadget.cpp
。
我一直在尝试按照 this Qt wiki page 上的说明实现 Pimpl class,其中私有 class 继承自另一个私有基础 class。
这是一个基本示例:
基地class
页眉
// gadget.h
#ifndef GADGET_H
#define GADGET_H
#include <QWidget>
class GadgetPrivate;
class Gadget : public QWidget
{
Q_OBJECT
public:
explicit Gadget(QWidget *parent = 0);
~Gadget();
protected:
Gadget(GadgetPrivate &d, QWidget *parent = 0);
GadgetPrivate *d_ptr;
private:
Q_DISABLE_COPY(Gadget)
Q_DECLARE_PRIVATE(Gadget)
};
#endif // GADGET_H
实施
// gadget.cpp
#include "gadget.h"
#include "gadget_p.h"
Gadget::Gadget(QWidget *parent)
: QWidget(parent),
d_ptr(new GadgetPrivate(this))
{}
Gadget::~Gadget() {}
Gadget::Gadget(GadgetPrivate &d, QWidget *parent)
: QWidget(parent),
d_ptr(&d)
{}
私人class
// gadget_p.h
#ifndef GADGET_P_H
#define GADGET_P_H
#include "gadget.h"
class GadgetPrivate
{
Q_DECLARE_PUBLIC(Gadget)
public:
GadgetPrivate(Gadget *q);
Gadget *q_ptr;
};
GadgetPrivate::GadgetPrivate(Gadget *q)
: q_ptr(q)
{}
#endif // GADGET_P_H
亚class
页眉
// gizmo.h
#ifndef GIZMO_H
#define GIZMO_H
#include "gadget.h"
class GizmoPrivate;
class Gizmo : public Gadget
{
Q_OBJECT
public:
explicit Gizmo(QWidget *parent = 0);
~Gizmo();
private:
Q_DISABLE_COPY(Gizmo)
Q_DECLARE_PRIVATE(Gizmo)
};
#endif // GIZMO_H
实施
// gizmo.cpp
#include "gizmo.h"
#include "gadget_p.h"
class GizmoPrivate : public GadgetPrivate
{
Q_DECLARE_PUBLIC(Gizmo)
public:
GizmoPrivate(Gizmo *q);
};
GizmoPrivate::GizmoPrivate(Gizmo *q)
: GadgetPrivate(q)
{}
Gizmo::Gizmo(QWidget *parent)
: Gadget(*new GizmoPrivate(this), parent)
{}
Gizmo::~Gizmo() {}
我收到以下错误:
In function `GadgetPrivate::GadgetPrivate(Gadget*)':
error: multiple definition of `GadgetPrivate::GadgetPrivate(Gadget*)'
有谁知道我做错了什么吗?
这个构造函数声明:
Gadget(GadgetPrivate &d, QWidget *parent)
需要引用 GadgetPrivate
,此时它只是前向声明的 class。把参数类型换成指针就可以了:
Gadget(GadgetPrivate *d, QWidget *parent)
和:
Gadget(GadgetPrivate *d, QWidget *parent)
: QWidget(parent), d_ptr(d)
{}
一些注意事项:
- 首先,为您的
d_ptr
使用QScopedPointer
。这将防止您因未删除d_ptr
而造成的内存泄漏。q_ptr
应该保持原始指针。 - This Q&A 关于 PIMPL 习语非常棒,包括很多关于 "gotcha" 等的提示。
- Marc Mutz 撰写了一些关于 Qt 和 pimpl idiom 的精彩文章。他们身价 checking out。我链接到文章的第 2 部分,因为它详细介绍了内部结构。
解决方案 #1:
使私有库中的所有内容 class 内联,即更改此设置,
class GadgetPrivate
{
Q_DECLARE_PUBLIC(Gadget)
public:
GadgetPrivate(Gadget *q);
Gadget *q_ptr;
};
GadgetPrivate::GadgetPrivate(Gadget *q)
: q_ptr(q)
{
}
到,
class GadgetPrivate
{
Q_DECLARE_PUBLIC(Gadget)
public:
GadgetPrivate(Gadget *q)
: q_ptr(q)
{
}
Gadget *q_ptr;
};
编译代码。
解决方案 #2:
这似乎也有效:
gadget_p.h
class GadgetPrivate
{
Q_DECLARE_PUBLIC(Gadget)
public:
GadgetPrivate(Gadget *q);
Gadget *q_ptr;
};
gadget.cpp
#include "gadget.h"
#include "gadget_p.h"
GadgetPrivate::GadgetPrivate(Gadget *q)
: q_ptr(q)
{
}
Gadget::Gadget(QWidget *parent)
: QWidget(parent),
d_ptr(new GadgetPrivate(this))
{
}
Gadget::~Gadget()
{
}
Gadget::Gadget(GadgetPrivate *d, QWidget *parent)
: QWidget(parent),
d_ptr(d)
{
}
GadgetPrivate
的实施已移至 gadget.cpp
。