我目前遇到了模板化方法的问题。我有这个实现模板方法的公共类:
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); }
}
内部类以这样的方式实现:
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; }
}
由于这个内部类头不能与提供的源一起使用,我必须在PublicClass头中转发它,然后在PublicClass.cpp文件中添加include到PrivateClass.h。
1)知道为什么我会收到以下错误:
错误:成员访问不完整类型'Private :: InternalClass'/ note:forward&gt;'Private :: InternalClass'的声明
2)隐藏我的PublicClass :: Add()实现的最佳方法是什么?
已更新
1)的错误原因是由于Cornstalks所说的this。
对于2),如何在不在PublicClass头文件中包含PrivateClass.h的情况下隐藏我的实现?
答案 0 :(得分:3)
您遇到了一个非常有趣的问题 - 您希望实现 PImpl idiom ,其中私有实现的类具有模板方法。好吧,这可以解决,这意味着您可以隐藏模板的实现,但只有当您知道将使用哪些类型来实例化您的程序中的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
档案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);
}
档案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;
}