我目前遇到了模板化方法的问题.我有这个实现模板方法的公共类:
namespace Private { class InternalClass; }
namespace Public
{
class PublicClass
{
public:
PublicClass();
virtual ~PublicClass();
template<class T>
bool Add(bool primary);
private:
Private::InternalClass* _pInternal;
};
template<class T>
bool PublicClass::Add(bool primary) { return _pInternal->Add<T>(primary); }
}
Run Code Online (Sandbox Code Playgroud)
内部类以这种方式实现:
namespace Private
{
class InternalClass
{
public:
InternalClass();
virtual ~InternalClass();
template <class T>
bool Add(bool primary);
};
template<class T>
bool InternalClass::Add(bool primary) { return false; }
}
Run Code Online (Sandbox Code Playgroud)
由于这个内部类头不能与提供的源一起使用,我必须在PublicClass头中转发它,并在PublicClass.cpp文件中添加include到PrivateClass.h.
1)知道为什么我会收到以下错误:
错误:成员访问不完整类型'Private :: InternalClass'/ note:forward>'Private :: InternalClass'的声明
2)隐藏我的PublicClass :: Add()实现的最佳方法是什么?
更新
原因1错误),是因为这是由玉米秆说.
对于2),如何在不在PublicClass头文件中包含PrivateClass.h的情况下隐藏我的实现?
您遇到了一个非常有趣的问题 - 您想要实现PImpl 习惯用法,其中私有实现的类具有模板方法。好吧,这个问题可以解决,这意味着您可以隐藏模板的实现,但前提是您知道哪些类型将用于Add<T>在程序中实例化您的方法。
假设您的模板仅适用于类型AClass和BClass。然后您可以按如下方式拆分文件(注释已内联):
文件 public.h:
#ifndef PUBLIC_H
#define PUBLIC_H
// Forward declaration ! It's sufficient in this case !
namespace Private { class InternalClass; }
// Declare all classes your Add<T> method should work with
struct AClass {};
struct BClass {};
namespace Public
{
class PublicClass
{
public:
PublicClass() {}
virtual ~PublicClass() {}
template <typename T>
bool Add(bool primary); // DO NOT implement this method, just declare
private:
Private::InternalClass* _pInternal;
};
// "Explicit instantiation declarations", for each type the method will work with:
extern template bool PublicClass::Add<AClass>(bool primary);
extern template bool PublicClass::Add<BClass>(bool primary);
}
#endif
Run Code Online (Sandbox Code Playgroud)
文件public.cpp:
#include "public.h"
// NOTE: this is hidden in CPP file, noone will see your implementation
namespace Private
{
class InternalClass
{
public:
InternalClass() {}
virtual ~InternalClass() {}
template <typename T>
bool Add(bool primary);
};
// Magic! Here is the actual implementation of your private method
template <typename T>
bool InternalClass::Add(bool primary)
{
return false;
}
}
namespace Public
{
// Original definition moved to CPP file !
template <typename T>
bool PublicClass::Add(bool primary)
{
return _pInternal->Add<T>(primary);
}
// And again list the allowed types, this time using "explicit instantiation definitions"
template bool PublicClass::Add<AClass>(bool primary);
template bool PublicClass::Add<BClass>(bool primary);
}
Run Code Online (Sandbox Code Playgroud)
文件main.cpp:
#include "public.h"
int main()
{
Public::PublicClass pc;
pc.Add<AClass>(true); // works !
pc.Add<BClass>(false); // works !
// pc.Add<int>(true); linker error as expected,
// becuase there is no explicit instantiation for Add<int>
return 0;
}
Run Code Online (Sandbox Code Playgroud)