Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ C+中的跨平台OOP+;_C++_Oop_Cross Platform - Fatal编程技术网

C++ C+中的跨平台OOP+;

C++ C+中的跨平台OOP+;,c++,oop,cross-platform,C++,Oop,Cross Platform,当然,我知道最好的答案是“不要写你自己的跨平台代码,有人已经做了你需要的”,但我这样做是作为一种爱好/学习练习,而不是以任何付费的身份。基本上,我在C++中编写了一个小的控制台应用程序,我想让它跨平台,处理文件、套接字和线程之类的东西。OOP似乎是处理这个问题的一个很好的方法,但是我还没有找到一个好的模式来编写跨平台共享相同接口的类 简单的方法是规划一些元接口,在程序的其余部分使用它,根据平台的不同使用不同的文件编译同一个类,但我觉得必须有一种更好的方法,更优雅;至少,一些不会混淆Intelli

当然,我知道最好的答案是“不要写你自己的跨平台代码,有人已经做了你需要的”,但我这样做是作为一种爱好/学习练习,而不是以任何付费的身份。基本上,我在C++中编写了一个小的控制台应用程序,我想让它跨平台,处理文件、套接字和线程之类的东西。OOP似乎是处理这个问题的一个很好的方法,但是我还没有找到一个好的模式来编写跨平台共享相同接口的类

简单的方法是规划一些元接口,在程序的其余部分使用它,根据平台的不同使用不同的文件编译同一个类,但我觉得必须有一种更好的方法,更优雅;至少,一些不会混淆IntelliSense及其同类的东西会很好

我查看了wxWidgets源代码中的一些较小的类,它们使用一种方法,使用一个私有成员来保存类的数据,例如

class Foo
{
    public:
        Foo();

        void Bar();
    private:
        FooData data;
};
然后,您可以通过根据平台选择不同的实现文件来编译它。这种方法在我看来相当笨拙

我考虑的另一种方法是编写一个接口,并根据平台交换从该接口继承的类。大概是这样的:

class Foo
{
    public:
        virtual ~Foo() {};
        virtual void Bar() = 0;
};

class Win32Foo
{
    public:
        Win32Foo();
        ~Win32Foo();
        void Bar();
};
当然,这种情况会破坏实际的实例化,因为您不知道要为哪个实现创建对象,但是可以通过使用函数来解决

Foo* CreateFoo();
并根据您运行的平台改变功能的实现。我也不是一个超级粉丝,因为它仍然用一堆实例化方法乱扔代码(这也与创建非跨平台对象的方法不一致)

这两种方法中哪一种更好?有更好的办法吗


<> > >编辑:,我的问题不是“如何编写跨平台C++”,而是“用C++中的类抽象跨平台代码的最佳方法是什么,同时尽可能保留类型系统的好处?”

< P>实际需要实现需要OS支持的跨平台功能,(比如sockets)您将不得不编写无法在特定平台上编译的代码。这意味着您的面向对象设计将需要使用预处理器指令进行补充


但由于您无论如何都必须使用预处理器,因此像
win32socket
(例如)这样的东西是否从
套接字继承而来的
基类甚至是必要的或有用的。当运行时以多态方式选择不同的函数时,OO通常很有用。但跨平台功能通常更像是编译时的问题。(例如,如果该函数甚至没有在Linux上编译,则以多态方式调用
win32socket::connect
是没有用的!)因此,最好只创建一个
socket
类,该类根据使用预处理器指令的平台的不同而实现不同。

第二种方法更好,因为它允许您创建仅存在于其中一个平台上的成员函数。然后,您可以在平台中使用抽象类orm独立代码,以及平台特定代码中的具体类

例如:

class Foo
{
    public:
        virtual ~Foo() {};
        virtual void Bar() = 0;
};   
class Win32Foo : public Foo
{
    public:
        void Bar();
        void CloseWindow(); // Win32-specific function
};

class Abc
{
    public:
        virtual ~Abc() {};
        virtual void Xyz() = 0;
};   
class Win32Abc : public Abc
{
    public:
        void Xyz()
        {
           // do something
           // and Close the window
           Win32Foo foo;
           foo.CloseWindow();
        }
};

理想情况下,您可以将差异集中在尽可能低的级别。
因此,顶级代码调用Foo(),只有Foo()需要在内部关注它调用的操作系统


注意:看看“boost”,它包含了很多处理跨平台网络文件系统等的东西,定义您的接口,它转发到
详细信息
调用:

#include "detail/foo.hpp"

struct foo
{
    void some_thing(void)
    {
        detail::some_thing();
    }
}
其中“detail/foo.hpp”类似于:

namespace detail
{
    void some_thing(void);
}
然后,您将在
detail/win32/foo.cpp
detail/posix/foo.cpp
中实现这一点,并根据编译所针对的平台,编译一个或另一个


公共接口只是将调用转发到特定于实现的实现。这与boost的方式类似。您需要查看boost以获得完整的详细信息。

在您的第一个示例中或GMan的授权工作得非常好,特别是当特定于平台的部分需要许多特定于平台的成员时(例如,只存在于一个平台中的类型的成员)。缺点是您必须维护两个类


如果类变得更简单,没有很多特定于平台的成员,那么您可以只使用一个公共类声明,并在两个不同的.cc文件中编写两个实现(对于独立于平台的方法实现,可能还有第三个.cc)。对于少数平台特定的成员或具有平台特定类型的成员,您可能需要在头文件中添加一些IFDEF。这种方式更像是一种黑客行为,但可以更容易地开始使用。如果代理失控,您可以随时切换到代理。

跨平台不需要执行OOP。跨平台更像是一种架构结构与设计范式

我建议将所有特定于平台的代码与标准代码(如sockets GUI)隔离。跨不同平台比较这些代码,并编写通用层或包装器。在代码中使用此层。创建库函数以实现通用层的特定于平台的实现


特定于平台的函数应位于单独的库或文件中。您的生成过程应为特定平台使用正确的库。您的“标准”不应更改代码。

正如其他人所指出的,继承对于作业来说是一个错误的工具。在您的案例中使用的具体类型的决定是在构建时做出的,而经典的多态性使该决定能够在运行时做出(即,作为用户操作的结果)。

您可以使用模板专门化来分离c
enum platform {mac, lin, w32};

template<platform p = mac>
struct MyClass
{
 // Platform dependent stuff for whatever platform you want to build for default here...
};

template<>
struct MyClass<lin>
{
 // Platform dependent stuff for Linux...
};

template<>
struct MyClass<w32>
{
 // Platform dependent stuff for Win32...
};

int main (void)
{
 MyClass<> formac;
 MyClass<lin> forlin
 MyClass<w32> forw32;
 return 0;
}