【问题标题】:Multiple definition error when creating Private subclass in Qt Pimpl class在 Qt Pimpl 类中创建私有子类时出现多个定义错误
【发布时间】:2016-09-12 09:23:26
【问题描述】:

我一直在尝试按照this Qt wiki page 上的说明实现一个 Pimpl 类,其中私有类继承自另一个私有基类。

这是一个基本的例子:

基类

标题

// 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)
{}

私人课

// 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

子类

标题

// 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*)'

有人知道我在这里做错了什么吗?

【问题讨论】:

    标签: c++ qt inheritance pimpl-idiom


    【解决方案1】:

    解决方案 #1:

    使私有基类中的所有内容内联,即更改它,

    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

    【讨论】:

      【解决方案2】:

      这个构造函数声明:

      Gadget(GadgetPrivate &d, QWidget *parent)
      

      需要引用GadgetPrivate,此时它只是一个前向声明的类。将参数类型切换为指针就可以了:

      Gadget(GadgetPrivate *d, QWidget *parent)
      

      和:

      Gadget(GadgetPrivate *d, QWidget *parent)
        : QWidget(parent), d_ptr(d)
        {}
      

      一些注意事项:

      • 首先,为您的d_ptr 使用QScopedPointer。这将防止您没有删除d_ptr 的内存泄漏。 q_ptr 应保持为原始指针。
      • PIMPL 成语上的This Q&A 非常棒,其中包含许多关于“陷阱”之类的提示。
      • Marc Mutz 写了一些关于 Qt 和 pimpl idiom 的精彩文章。他们值得checking out。我链接到文章的第 2 部分,因为它涉及到更多的内部细节。

      【讨论】:

      • 为什么Gadget(*new GizmoPrivate(this), parent)不对应Gadget(GadgetPrivate &amp;d, QWidget *parent = 0);
      • @kfsone Duh...确实如此。我一定为那个签名看了三遍,但没有看到它。
      • 您对内存泄漏的看法是正确的。我删除了QScopedPointer,因为我不确定它是否与错误有关。
      • 我尝试了您的建议,但仍然遇到相同的编译器错误。我认为问题在于gadget_p.h 包含在gizmo.cppgadget.cpp 中。如果我将所有内容都内联在私有基类中,它就可以工作。请参阅我的单独答案。
      • 单独的cpp 包含相同标题的文件不应导致此类错误。你有可能有一个内联外联定义吗?
      猜你喜欢
      • 1970-01-01
      • 2017-10-27
      • 1970-01-01
      • 2013-11-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多