我可能会去一个政策性的东西:
template<typename Platform>
struct PlatDetails : private Platform {
std::string getDetails() const {
return std::string("MyAbstraction v1.0; ") + getName();
}
};
// For any serious compatibility functions, these would
// of course have to be in different headers, and the implementations
// would call some platform-specific functions to get precise
// version numbers. Using PImpl would be a smart idea for these
// classes if they need any platform-specific members, since as
// Joe Gauterin says, you want to avoid your application code indirectly
// including POSIX or Windows system headers, containing useless definitions.
struct Windows {
std::string getName() const { return "Windows"; }
};
struct Linux {
std::string getName() const { return "Linux"; }
};
#ifdef WIN32
typedef PlatDetails<Windows> PlatformDetails;
#else
typedef PlatDetails<Linux> PlatformDetails;
#endif
int main() {
std::cout << PlatformDetails().getName() << "\n";
}
有没有一个整体很多选择,虽然这样做,并定期做模拟动态与CRTP结合之间,所以通用事物是派生类的基础和具体事物:
template<typename Platform>
struct PlatDetails {
std::string getDetails() const {
return std::string("MyAbstraction v1.0; ") +
static_cast<Platform*>(this)->getName();
}
};
struct Windows : PlatDetails<Windows> {
std::string getName() const { return "Windows"; }
};
struct Linux : PlatDetails<Linux> {
std::string getName() const { return "Linux"; }
};
#ifdef WIN32
typedef Windows PlatformDetails;
#else
typedef Linux PlatformDetails;
#endif
int main() {
std::cout << PlatformDetails().getName() << "\n";
}
基本上在后一版本中,getName
必须是公开的(尽管我认为你可以使用friend
),所以必须是继承,而在前者中,继承可以是私有的和/或可以保护接口函数(如果需要的话)。所以适配器可以是平台必须实现的接口和应用程序代码使用的接口之间的防火墙。此外,前者可以有多个策略(即相同平台无关的类使用多个平台相关的方面),但不适用于后者。
它们中的任何一个优于具有委托或非模板使用继承的版本的优点是您不需要任何虚拟功能。可以说,这不是一个很大的优势,考虑到基于策略的设计和CRTP最初接触的可怕程度。
但在实践中,我同意quamrana,通常你可以有同样的事情,不同的实现在不同的平台:
// Or just set the include path with -I or whatever
#ifdef WIN32
#include "windows/platform.h"
#else
#include "linux/platform.h"
#endif
struct PlatformDetails {
std::string getDetails() const {
return std::string("MyAbstraction v1.0; ") +
porting::getName();
}
};
// windows/platform.h
namespace porting {
std::string getName() { return "Windows"; }
}
// linux/platform.h
namespace porting {
std::string getName() { return "Linux"; }
}
要扔在进一步阅读一些检索词:我觉得这也被称为“桥模式”或“实现模式”。 – foraidt 2010-03-10 00:02:52
有趣,这是我一直在做的。我有一个问题,如果你有两个平台,其中90%的代码在该类/文件的平台之间是相同的? – matt 2010-03-10 00:30:58
@matt:您可以使用通用的源文件; foo.h(平台无关),foo.cpp(包含公共代码),foo.win32.cpp,foo.posix.cpp。根据foo.cpp包含的内容,它可以被单独编译然后链接,或者只包含到foo.win32.cpp和foo.posix.cpp – 2010-03-10 00:50:13