C++ c++;我如何实现这种班级结构?

C++ c++;我如何实现这种班级结构?,c++,class,inheritance,cross-platform,C++,Class,Inheritance,Cross Platform,我绞尽脑汁想知道如何编写跨平台类,同时避免虚拟函数的成本和特定平台版本类中的任何丑陋之处。这是我试过的 平台独立类.hpp class PlatformIndependantClass { public: PlatformIndependantClass(); std::string GetPlatformName(); private: PlatformIndependantClass* mImplementation; };

我绞尽脑汁想知道如何编写跨平台类,同时避免虚拟函数的成本和特定平台版本类中的任何丑陋之处。这是我试过的

平台独立类.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;
}
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的解释是