类成员的前向类声明

Posted

技术标签:

【中文标题】类成员的前向类声明【英文标题】:Forwad class declaration for class members 【发布时间】:2014-07-14 19:45:17 【问题描述】:

我遇到了问题,因为我希望我的包含不包含在头文件中并将它们粘贴在源中以减少包含头。

虽然以下类使用 goocanvas 库,但问题在于普通 c++ 规则...

下面的类是使用另一个类的类(前向声明的)

#include <goocanvasmm/canvas.h> // due to: table main widget
namespace roulette

    class surface; // forward declared classes
    class mesh;

    class table final : public Goocanvas::Canvas
    
    public:
        table ();
    private:
        Glib::RefPtr<surface> m_surface;  // using forward declared classes
        Glib::RefPtr<mesh> m_mesh;
    ;

现在这里是上述“表”类的入口点

#include "surface.hpp"  // here we include forward declared classes
#include "mesh.hpp" // same here
#include "table.hpp"    // and the header it self

namespace roulette

    table::table() :  // ERROR: ALLOCATION OF INCOMPLETE TYPE
        m_surface(Glib::RefPtr<surface>(new surface)),  
        m_mesh(Glib::RefPtr<mesh>(new mesh(9, 29, 0, 0, 26, 19)))
    
             /* implementation */
    

在标题中包含标题“mesh”和“surface”而不是源文件时,一切都很好。 如何解决这个问题,这样我就不必在头文件中包含头文件了?

编辑: 这是“网格”和“表面”的标题

#include <goocanvasmm/table.h> // due to: inheritance

namespace roulette

    class mesh final : public Goocanvas::Table
    
    public:
        mesh (short rows, short columns,
                double x = 0.0,
            double y = 0.0,
            double width = 0.0,
            double height = 0.0);
;

#include <string>   // due to: image path placeholder
#include <gdkmm/pixbuf.h>   // due to: image loading
#include <goocanvasmm/itemsimple.h> // due to: ItemSimple class inheritance

class surface final : public Goocanvas::ItemSimple

public:
    surface ();

    Glib::RefPtr<Gdk::Pixbuf> get_chip(short value);

private:
    // members
    std::string m_data_path;
    Glib::RefPtr<Gdk::Pixbuf> m_image;
    Glib::RefPtr<Gdk::Pixbuf> m_chip1, m_chip5, m_chip25, m_chip50, m_chip100;

    // methods
    void simple_paint_vfunc(const Cairo::RefPtr<Cairo::Context>& cr, const Goocanvas::Bounds& bounds) override;
;

【问题讨论】:

“我希望我的包含不在头文件中” 为什么?您是否阅读了一些建议这是一种好的做法? 您能否进一步详细说明究竟是什么代码导致了您的编译器的哪些错误消息?您应该只需要在源文件中包含meshsurface 显示(可能缩短)surface.hpp 和mesh.hpp。 我可能是错的,但这可能是您有默认析构函数的问题。默认析构函数将在头文件中定义,并且(我假设)需要定义 Glib::RefPtr 来执行此操作。 @Mark B 是的,这正是问题所在,由于错误(使用不完整类型),我无法将它们包含在源文件中,我必须按顺序将它们包含在 heder 文件(table.hpp)中完成这项工作 【参考方案1】:

它看起来像Glib::RefPtr,像许多其他智能指针一样,需要一个完整的类型,而不仅仅是前向声明。因此,恐怕您需要在 table 标头中包含标头。或者您可以使用 Pimpl idiom - 参见例如http://herbsutter.com/gotw/_100/.

【讨论】:

我会坚持你的建议,pimpl idiom 似乎会带来额外的开销,所以我不会使用它。谢谢

以上是关于类成员的前向类声明的主要内容,如果未能解决你的问题,请参考以下文章

成员结构的前向声明

为啥我不能只用前向声明 C++ 声明一个类的静态成员?

英特尔编译器不编译另一个类中的私有前向类声明

将声明的枚举转发为类成员变量

前向声明

关于声明定义前向声明include循环依赖普通友元函数友元类友元成员函数的总结