如何转发声明第三方结构

How to forward declare third-party struct

本文关键字:声明 第三方 结构 转发 何转发      更新时间:2023-10-16

在我的原始代码中,我引用了ClassOne头文件中的第三方.H,一切都很好。现在,我收到了一个新的要求,不允许我引用ClassOne头文件中的第三方.H。这样,我的代码的使用者(即ClassOne)就不必间接包含第三方.H文件。我试过以下修改,但不起作用。

这是示例代码:

// third_party.h
struct PPP
{
    int x;
    int y;
}; // without default constructor
// Original code!
//////////////////////////////////////////////
// ClassOne.h // my class
#include <third_party.h> // refer to the .H in header file
namespace X
{
    class ClassOne
    {
    ...
    private:
        boost::scoped_ptr<PPP> m_scpPPP;    
    };
}
// ClassOne.cpp
#include <third_party.h>
namespace X
{
    ClassOne::ClassOne()
    {
        m_scpPPP.reset( new PPP() ); // fine
    }
    ...
}
// Modified code!
==========================================================
// ClassOne.h
struct PPP; // error C2371: 'PPP' : redefinition; different basic types
namespace X
{
    class ClassOne
    {
    ...
    private:
        boost::scoped_ptr<PPP> m_scpPPP;    
    };
}
// ClassOne.cpp
#include <third_party.h>
namespace X
{
    ClassOne::ClassOne()
    {
        m_scpPPP.reset( new PPP() ); // now see errors. 
        // error C2512: 'PPP' : no appropriate default constructor available
    }
    ...
}

问题1>我应该在哪里转发声明第三方结构类型PPP

问题2>为什么编译器现在抱怨PPP没有默认构造函数?

实例化类型不完整的模板不是标准行为,因此它不应该在boost::scoped_ptr中工作。

话虽如此,unique_ptr有一个特殊的规则,允许采用不完全类型。如果你使用它(而不是boost::scoped_ptr),那么它是这样做的:

// forward declaration of PPP, assuming c++ header
struct PPP;
namespace X
{
    class ClassOne
    {
    ...
    private:
        std::unique_ptr<PPP> m_scpPPP;    
    };
}

简单地说:那行不通。由于您在ClassOne中使用PPP(而不是PPP*),编译器需要知道此时的大小,因此需要来知道PPP的定义。要在公共.h文件中隐藏PPP,您需要做更多的操作。一种可能的解决方案是将实现类隐藏在另一个类后面。另一种方法是只在类声明中引用PPP*(尽管这会使scoped_ptr<>的使用变得有点毫无意义)。

编译器期望有一个默认构造函数,因为他假定有一个。他也需要这个类的定义来称之为"新"。您可以通过将ctor的实现移动到.cpp文件来解决此问题,可以在其中包含thirdParty.h。