繁体   English   中英

c ++如何实现此类结构?

[英]c++ How Can I Achieve This Class Structure?

我正在绞尽脑汁试图找出如何编写跨平台类,同时避免虚拟函数的成本和平台特定版本的类中的任何丑陋。 这是我尝试过的。

PlatformIndependantClass.hpp

class PlatformIndependantClass {
    public:
        PlatformIndependantClass();
        std::string GetPlatformName();
    private:
        PlatformIndependantClass* mImplementation;

};

LinuxClass.hpp

#include "PlatformIndependantClass.hpp"
class LinuxClass : public PlatformIndependantClass{
    public:
        std::string GetPlatformName();
};

WindowsClass.hpp

#include "PlatformIndependantClass.hpp"
class WindowsClass : public PlatformIndependantClass {
    public:
        std::string GetPlatformName();
};

PlatformIndependantClass.cpp

#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();
}

LinuxClass.cpp

#include "LinuxClass.hpp"
std::string LinuxClass::GetPlatformName() {
    return std::string("This was compiled on linux!");
}

WindowsClass.cpp

#include "WindowsClass.hpp"
std::string WindowsClass::GetPlatformName() {
    return std::string("This was compiled on windows!");
}

main.cpp中

#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;
}

现在,这编译得很好但我得到了一个分段错误。 我相信这是因为平台特定的类继承自PlatformIndependantClass,它在构造时创建了特定于平台的类的实例,因此我获得了无限的递归。 每次我尝试,我都会非常困惑!

如何才能正确实现这样的设计? 或者这只是一个可怕的想法。 我一直试图找出如何编写跨平台类,但我只是得到了一些关于跨平台库的结果,任何帮助都将被感激地接受:)

从最后开始,是的,真的是一个可怕的想法,大多数想法都以“我想避免虚拟功能的成本”开头。

至于你为什么会遇到分段错误(特别是堆栈溢出),这是因为你没有使用虚函数,而是使用静态链接。 编译器不知道mImplementation只是一个PlatformIndependantClass ,所以当你尝试调用return mImplementation->GetPlatformName()你会return mImplementation->GetPlatformName()调用同一个函数。

你所取得的成就叫做阴影 ,你正在使用编译时功能解析。 编译器将调用您正在调用它的变量的实际类型GetPlatformName函数,因为没有虚拟表来覆盖指向实际函数的指针。 由于mImplementationPlatformIndependantClass ,因此mImplementation->GetPlatformName将始终为PlatformIndependantClass::GetPlatformName

编辑:当然,我想到了为什么你需要同时创建引擎的Windows和Linux副本的问题。 你永远不会同时使用它们,对吧?

那么为什么不只是有两个不同的库,每个系统一个,并从您的makefile链接正确的库。 你将获得最好的世界!

我认为你想要完成的事情可以更轻松地完成......

Object.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();      
};

Object.cpp

#include "Object.h"

void Object::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

等等。 我认为这可以通过更简单的方式完成您的尝试。 此外,不需要虚拟功能。

我将创建一个静态工厂方法来创建实例,而不是使用构造函数来构建特定于平台的实例:

PlatformIndependantClass* PlatformIndependantClass::getPlatformIndependantClass() {
    #ifdef TARGET_LINUX
        return new LinuxClass();
    #endif
    #ifdef TARGET_WINDOWS
        return new WindowsClass();
    #endif
}

这样可以避免递归,也不需要mImplementation指针。

我也会尝试避免特定于平台的类,但这是另一个故事:)

当您希望具有多态行为而没有任何运行时开销时,您可以尝试奇怪的重复模板模式(CRTP) 基类是模板,派生类将自身用作基础的模板参数。 这需要将您的类定义为模板,这进一步限制它们完全在头(.hpp)文件中实现。

我不确定如何在您的特定情况下应用该模式。

我不认为构造函数导致无限递归。 这是GetPlatformName()函数。 因为它没有设置为虚拟,所以它只能调用自身。

两个解决方案:使该功能成为虚拟,或完全取消继承。

无论哪种方式,仅调用另一个函数的函数的成本将首先比使用虚函数更昂贵。 所以我会说保留继承,虚拟化特定于平台的函数,并直接调用它们,而无需通过基类函数。

你对infinte循环是正确的。 修复实际上比你想象的要容易。

PlatformIndependantClass.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

};

LinuxClass.cpp

#ifdef __GNUC__ 
#include //linux headers
#include "PlatformIndependantClass.hpp"
struct PlatformDependantClass { //linux only stuff
     //stuff
};    

PlatformIndependantClass() {
    mImplementation.reset(new PlatformDependantClass );
}
~PlatformIndependantClass() {
}
std::string PlatformIndependantClass::GetPlatformName() {
    return std::string("This was compiled on linux!");
}
#endif //__GNUC__ 

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* thing被称为“不透明指针”或“pimpl idiom” http://en.wikipedia.org/wiki/Opaque_pointer

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM