C++ c++;我如何实现这种班级结构?
我绞尽脑汁想知道如何编写跨平台类,同时避免虚拟函数的成本和特定平台版本类中的任何丑陋之处。这是我试过的 平台独立类.hppC++ c++;我如何实现这种班级结构?,c++,class,inheritance,cross-platform,C++,Class,Inheritance,Cross Platform,我绞尽脑汁想知道如何编写跨平台类,同时避免虚拟函数的成本和特定平台版本类中的任何丑陋之处。这是我试过的 平台独立类.hpp class PlatformIndependantClass { public: PlatformIndependantClass(); std::string GetPlatformName(); private: PlatformIndependantClass* mImplementation; };
class PlatformIndependantClass {
public:
PlatformIndependantClass();
std::string GetPlatformName();
private:
PlatformIndependantClass* mImplementation;
};
#include "PlatformIndependantClass.hpp"
class LinuxClass : public PlatformIndependantClass{
public:
std::string GetPlatformName();
};
#include "PlatformIndependantClass.hpp"
class WindowsClass : public PlatformIndependantClass {
public:
std::string GetPlatformName();
};
#include "PlatformIndependantClass.hpp"
#include "LinuxClass.hpp"
#include "WindowsClass.hpp"
PlatformIndependantClass::PlatformIndependantClass() {
#ifdef TARGET_LINUX
mImplementation = new LinuxClass();
#endif
#ifdef TARGET_WINDOWS
mImplementation = new WindowsClass();
#endif
}
std::string PlatformIndependantClass::GetPlatformName() {
return mImplementation->GetPlatformName();
}
#include "LinuxClass.hpp"
std::string LinuxClass::GetPlatformName() {
return std::string("This was compiled on linux!");
}
#include "WindowsClass.hpp"
std::string WindowsClass::GetPlatformName() {
return std::string("This was compiled on windows!");
}
#include <iostream>
#include "PlatformIndependantClass.hpp"
using namespace std;
int main()
{
PlatformIndependantClass* cl = new PlatformIndependantClass();
cout << "Hello world!" << endl;
cout << "Operating system name is: " << cl->GetPlatformName() << endl;
cout << "Bye!" << endl;
return 0;
}
LinuxClass.hpp
class PlatformIndependantClass {
public:
PlatformIndependantClass();
std::string GetPlatformName();
private:
PlatformIndependantClass* mImplementation;
};
#include "PlatformIndependantClass.hpp"
class LinuxClass : public PlatformIndependantClass{
public:
std::string GetPlatformName();
};
#include "PlatformIndependantClass.hpp"
class WindowsClass : public PlatformIndependantClass {
public:
std::string GetPlatformName();
};
#include "PlatformIndependantClass.hpp"
#include "LinuxClass.hpp"
#include "WindowsClass.hpp"
PlatformIndependantClass::PlatformIndependantClass() {
#ifdef TARGET_LINUX
mImplementation = new LinuxClass();
#endif
#ifdef TARGET_WINDOWS
mImplementation = new WindowsClass();
#endif
}
std::string PlatformIndependantClass::GetPlatformName() {
return mImplementation->GetPlatformName();
}
#include "LinuxClass.hpp"
std::string LinuxClass::GetPlatformName() {
return std::string("This was compiled on linux!");
}
#include "WindowsClass.hpp"
std::string WindowsClass::GetPlatformName() {
return std::string("This was compiled on windows!");
}
#include <iostream>
#include "PlatformIndependantClass.hpp"
using namespace std;
int main()
{
PlatformIndependantClass* cl = new PlatformIndependantClass();
cout << "Hello world!" << endl;
cout << "Operating system name is: " << cl->GetPlatformName() << endl;
cout << "Bye!" << endl;
return 0;
}
WindowsClass.hpp
class PlatformIndependantClass {
public:
PlatformIndependantClass();
std::string GetPlatformName();
private:
PlatformIndependantClass* mImplementation;
};
#include "PlatformIndependantClass.hpp"
class LinuxClass : public PlatformIndependantClass{
public:
std::string GetPlatformName();
};
#include "PlatformIndependantClass.hpp"
class WindowsClass : public PlatformIndependantClass {
public:
std::string GetPlatformName();
};
#include "PlatformIndependantClass.hpp"
#include "LinuxClass.hpp"
#include "WindowsClass.hpp"
PlatformIndependantClass::PlatformIndependantClass() {
#ifdef TARGET_LINUX
mImplementation = new LinuxClass();
#endif
#ifdef TARGET_WINDOWS
mImplementation = new WindowsClass();
#endif
}
std::string PlatformIndependantClass::GetPlatformName() {
return mImplementation->GetPlatformName();
}
#include "LinuxClass.hpp"
std::string LinuxClass::GetPlatformName() {
return std::string("This was compiled on linux!");
}
#include "WindowsClass.hpp"
std::string WindowsClass::GetPlatformName() {
return std::string("This was compiled on windows!");
}
#include <iostream>
#include "PlatformIndependantClass.hpp"
using namespace std;
int main()
{
PlatformIndependantClass* cl = new PlatformIndependantClass();
cout << "Hello world!" << endl;
cout << "Operating system name is: " << cl->GetPlatformName() << endl;
cout << "Bye!" << endl;
return 0;
}
平台独立类.cpp
class PlatformIndependantClass {
public:
PlatformIndependantClass();
std::string GetPlatformName();
private:
PlatformIndependantClass* mImplementation;
};
#include "PlatformIndependantClass.hpp"
class LinuxClass : public PlatformIndependantClass{
public:
std::string GetPlatformName();
};
#include "PlatformIndependantClass.hpp"
class WindowsClass : public PlatformIndependantClass {
public:
std::string GetPlatformName();
};
#include "PlatformIndependantClass.hpp"
#include "LinuxClass.hpp"
#include "WindowsClass.hpp"
PlatformIndependantClass::PlatformIndependantClass() {
#ifdef TARGET_LINUX
mImplementation = new LinuxClass();
#endif
#ifdef TARGET_WINDOWS
mImplementation = new WindowsClass();
#endif
}
std::string PlatformIndependantClass::GetPlatformName() {
return mImplementation->GetPlatformName();
}
#include "LinuxClass.hpp"
std::string LinuxClass::GetPlatformName() {
return std::string("This was compiled on linux!");
}
#include "WindowsClass.hpp"
std::string WindowsClass::GetPlatformName() {
return std::string("This was compiled on windows!");
}
#include <iostream>
#include "PlatformIndependantClass.hpp"
using namespace std;
int main()
{
PlatformIndependantClass* cl = new PlatformIndependantClass();
cout << "Hello world!" << endl;
cout << "Operating system name is: " << cl->GetPlatformName() << endl;
cout << "Bye!" << endl;
return 0;
}
LinuxClass.cpp
class PlatformIndependantClass {
public:
PlatformIndependantClass();
std::string GetPlatformName();
private:
PlatformIndependantClass* mImplementation;
};
#include "PlatformIndependantClass.hpp"
class LinuxClass : public PlatformIndependantClass{
public:
std::string GetPlatformName();
};
#include "PlatformIndependantClass.hpp"
class WindowsClass : public PlatformIndependantClass {
public:
std::string GetPlatformName();
};
#include "PlatformIndependantClass.hpp"
#include "LinuxClass.hpp"
#include "WindowsClass.hpp"
PlatformIndependantClass::PlatformIndependantClass() {
#ifdef TARGET_LINUX
mImplementation = new LinuxClass();
#endif
#ifdef TARGET_WINDOWS
mImplementation = new WindowsClass();
#endif
}
std::string PlatformIndependantClass::GetPlatformName() {
return mImplementation->GetPlatformName();
}
#include "LinuxClass.hpp"
std::string LinuxClass::GetPlatformName() {
return std::string("This was compiled on linux!");
}
#include "WindowsClass.hpp"
std::string WindowsClass::GetPlatformName() {
return std::string("This was compiled on windows!");
}
#include <iostream>
#include "PlatformIndependantClass.hpp"
using namespace std;
int main()
{
PlatformIndependantClass* cl = new PlatformIndependantClass();
cout << "Hello world!" << endl;
cout << "Operating system name is: " << cl->GetPlatformName() << endl;
cout << "Bye!" << endl;
return 0;
}
WindowsClass.cpp
class PlatformIndependantClass {
public:
PlatformIndependantClass();
std::string GetPlatformName();
private:
PlatformIndependantClass* mImplementation;
};
#include "PlatformIndependantClass.hpp"
class LinuxClass : public PlatformIndependantClass{
public:
std::string GetPlatformName();
};
#include "PlatformIndependantClass.hpp"
class WindowsClass : public PlatformIndependantClass {
public:
std::string GetPlatformName();
};
#include "PlatformIndependantClass.hpp"
#include "LinuxClass.hpp"
#include "WindowsClass.hpp"
PlatformIndependantClass::PlatformIndependantClass() {
#ifdef TARGET_LINUX
mImplementation = new LinuxClass();
#endif
#ifdef TARGET_WINDOWS
mImplementation = new WindowsClass();
#endif
}
std::string PlatformIndependantClass::GetPlatformName() {
return mImplementation->GetPlatformName();
}
#include "LinuxClass.hpp"
std::string LinuxClass::GetPlatformName() {
return std::string("This was compiled on linux!");
}
#include "WindowsClass.hpp"
std::string WindowsClass::GetPlatformName() {
return std::string("This was compiled on windows!");
}
#include <iostream>
#include "PlatformIndependantClass.hpp"
using namespace std;
int main()
{
PlatformIndependantClass* cl = new PlatformIndependantClass();
cout << "Hello world!" << endl;
cout << "Operating system name is: " << cl->GetPlatformName() << endl;
cout << "Bye!" << endl;
return 0;
}
main.cpp
class PlatformIndependantClass {
public:
PlatformIndependantClass();
std::string GetPlatformName();
private:
PlatformIndependantClass* mImplementation;
};
#include "PlatformIndependantClass.hpp"
class LinuxClass : public PlatformIndependantClass{
public:
std::string GetPlatformName();
};
#include "PlatformIndependantClass.hpp"
class WindowsClass : public PlatformIndependantClass {
public:
std::string GetPlatformName();
};
#include "PlatformIndependantClass.hpp"
#include "LinuxClass.hpp"
#include "WindowsClass.hpp"
PlatformIndependantClass::PlatformIndependantClass() {
#ifdef TARGET_LINUX
mImplementation = new LinuxClass();
#endif
#ifdef TARGET_WINDOWS
mImplementation = new WindowsClass();
#endif
}
std::string PlatformIndependantClass::GetPlatformName() {
return mImplementation->GetPlatformName();
}
#include "LinuxClass.hpp"
std::string LinuxClass::GetPlatformName() {
return std::string("This was compiled on linux!");
}
#include "WindowsClass.hpp"
std::string WindowsClass::GetPlatformName() {
return std::string("This was compiled on windows!");
}
#include <iostream>
#include "PlatformIndependantClass.hpp"
using namespace std;
int main()
{
PlatformIndependantClass* cl = new PlatformIndependantClass();
cout << "Hello world!" << endl;
cout << "Operating system name is: " << cl->GetPlatformName() << endl;
cout << "Bye!" << endl;
return 0;
}
#包括
#包括“PlatformIndependentClass.hpp”
使用名称空间std;
int main()
{
PlatformIndependentClass*cl=新的PlatformIndependentClass();
cout从结尾开始,是的,这确实是一个可怕的想法,就像大多数以“我想避免虚拟功能的成本”开头的想法一样
至于为什么会出现分段错误(特别是堆栈溢出),这是因为您使用的不是虚拟函数,而是静态链接。编译器不知道miimplementation
不是platformindependenclass
,所以当您尝试调用return miimplementation->GetPlatformName()时
您反复调用同一个函数
您实现的是所谓的隐藏,您使用的是编译时函数解析。编译器将调用您调用它的变量的实际类型的GetPlatformName
函数,因为没有虚拟表来覆盖指向实际函数的指针。因为miimplementation
是PlatformIn依赖类
,miimplementation->GetPlatformName
将始终是platformindependentclass::GetPlatformName
编辑:当然,我会想到为什么你需要同时创建你的引擎的Windows和Linux副本。你永远不会同时使用它们,对吗
因此,为什么不使用两个不同的库,每个系统一个,并从makefile中链接正确的库呢?您将获得最佳效果!我将创建一个静态工厂方法来创建实例,而不是使用构造函数来构建特定于平台的实例:
PlatformIndependantClass* PlatformIndependantClass::getPlatformIndependantClass() {
#ifdef TARGET_LINUX
return new LinuxClass();
#endif
#ifdef TARGET_WINDOWS
return new WindowsClass();
#endif
}
这样可以避免递归,也不需要miimplementation指针
我也会尽量避免使用特定于平台的类,但这是另一种情况:)我认为您想要完成的事情可以更容易地完成
目标h:
#include <normal includes>
#if WINDOWS
#include <windows includes>
#endif
#if LINUX
#include <linux includes>
#endif
class Object
{
private:
#if WINDOWS
//Windows Specific Fields...
#endif
#if LINUX
//Linux Specific Fields...
#endif
public:
//Function that performs platform specific functionality
void DoPlatformSpecificStuff();
//Nothing platform specific here
void DoStuff();
};
ObjectWin32.cpp
#if WINDOWS
#include "Object.h"
void Object::DoPlatformSpecificStuff()
{
//Windows specific stuff...
}
#endif
ObjectLinux.cpp
#if LINUX
#include "Object.h"
void Object::DoPlatformSpecificStuff()
{
//Linux specific stuff...
}
#endif
以此类推。我认为这可以以更简单的方式完成您正在尝试的任务。此外,不需要虚拟函数。我认为构造函数不会导致无限递归。它是GetPlatformName()函数。因为它没有设置为虚拟函数,所以它只能调用自身
两种解决方案:使该函数虚拟化,或完全取消继承
无论哪种方式,一个函数只调用另一个函数的成本都会比使用虚拟函数的成本更高。因此,我想说的是,保留继承,虚拟化特定于平台的函数,直接调用它们,而不需要通过基类函数。当您想要具有多态行为时或者在没有任何运行时开销的情况下,您可以尝试。基类是一个模板,派生类将自身用作基类的模板参数。这要求将类定义为模板,从而进一步限制它们在头(.hpp)文件中完全实现
我不确定如何在您的特定情况下应用该模式。您对infinte循环的看法是正确的。修复实际上比您想象的要简单
platformindependentclass.hpp
#include //portable headers
struct PlatformDependantClass; //defined in Cpp file
class PlatformIndependantClass {
public:
PlatformIndependantClass();
~PlatformIndependantClass();
std::string GetPlatformName();
private:
std::unique_ptr<PlatformDependantClass> mImplementation; //note, different type
};
WindowsClass.cpp
#ifdef _MSC_VER
#include //windows headers
#include "PlatformIndependantClass.hpp"
struct PlatformDependantClass { //windows only stuff
//stuff
};
PlatformIndependantClass() {
mImplementation.reset(new PlatformDependantClass );
}
~PlatformIndependantClass() {
}
std::string PlatformIndependantClass::GetPlatformName() {
return std::string("This was compiled on Windows!");
}
#endif //_MSC_VER
这里只定义了一个类。在windows中,它只编译并包含windows内容,而在Linux中,它只编译并包含Linux内容。请注意,void*
东西被称为“不透明指针”或“pimpl惯用语”您所说的“平台无关性”是什么意思?虚拟功能的成本是多少?这足以让用户注意到吗?PS:“独立”没有“a”在C++中,“NedBaBeldter谢谢,我会在代码中更改:”这是条件编译的条件。无论如何,你需要用你的方案来编译条件。+ 1,击败我的多个库的想法,我已经离开C++太久了:“Blindy:有时候我希望离开C++一段时间,但是我总是回来……)这也需要特定于平台的头文件,不是吗?对于私有成员?我想将头文件分为不同的文件,而不是将其与预处理器指令混在一起,我如何使用这种方法来实现这一点?我将展示将公共类与实施类分开的代码,但是然后我突然意识到,你只需按照James所说的做,即将所有特定于实现的代码放在不同的特定于平台的源文件中,并共享同一个头文件。很简单。@Ell:更新了答案。你可以在头文件中定义特定于平台的字段,并用#if或#ifdef.-1包装,如何使指针成为void*
“简易修复”?delete miimplementation
甚至不会编译,您的类函数重新定义也不会编译……在您实际发表评论之前,我注意到并更正了它。我可以发誓我看到过带有void*的pImpl,但我做错了,我从我输入的wiki链接中更正了自己。这是我最初的想法之一,我不知道最后,我只是不喜欢有显式函数的事实,我想我试图做的是使用构造函数创建一个隐式工厂(如果这对您有意义的话),除了没有虚拟表,您仍然无法获得虚拟调用。segfault的解释是