代码之家  ›  专栏  ›  技术社区  ›  ShZ

C++中的跨平台面向对象编程

  •  10
  • ShZ  · 技术社区  · 16 年前

    简单的方法是规划一些元接口,在程序的其余部分使用它,根据平台的不同使用不同的文件编译同一个类,但我觉得必须有一种更好的方法,更优雅;至少,一些不会混淆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();
    

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

    8 回复  |  直到 16 年前
        1
  •  14
  •   GManNickG    16 年前

    detail 电话:

    #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 ,并根据编译的平台,编译其中一个。

        2
  •  15
  •   Charles Salvia    16 年前

    要真正实现需要操作系统支持的跨平台功能(如套接字),您必须编写简单的代码 不会编译

    但是,由于您无论如何都必须使用预处理器,因此是否使用 win32socket (例如)继承自 socket win32socket::connect 插座

        3
  •  4
  •   Thomas Matthews    16 年前

    你不需要为了跨平台而去OOP。跨平台更多的是一种架构和设计范式。

    特定于平台的功能应位于单独的库或文件中。构建过程应针对特定平台使用正确的库。您的“标准”代码不应更改。

        4
  •  2
  •   Martin Beckett    16 年前

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

    另外,看看“boost”,它包含了很多处理跨平台网络文件系统等的东西

        5
  •  1
  •   Igor    16 年前

    例子:

    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();
            }
    };
    
        6
  •  1
  •   Reed Hedges    16 年前

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

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

        7
  •  1
  •   Nemanja Trifunovic    16 年前

        8
  •  1
  •   haroon haroon    16 年前

    您可以使用模板专门化来分离不同平台的代码。

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