如何转发声明第三方结构

时间:2014-04-16 15:39:37

标签: c++

在我的原始代码中,我引用了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&gt;我应该在哪里转发声明第三方结构类型PPP

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

2 个答案:

答案 0 :(得分:1)

实例化具有不完整类型的模板不是标准行为,因此它不应该工作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;    
    };
}

答案 1 :(得分:0)

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

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