在我的原始代码中,我引用了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?
答案 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。