Межплатформенное ООП в C++

Большинство примеров, которые я считал, делает это или при помощи шаблона "команда" или при помощи шаблона "memento". Но можно сделать это без шаблонов разработки также с простым структура двухсторонней очереди .

11
задан ShZ 10 December 2009 в 23:26
поделиться

8 ответов

Определите свой интерфейс, который перенаправляет на подробные вызовы:

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

12
ответ дан 3 December 2019 в 01:44
поделиться

Вы можете использовать специализацию шаблонов для разделения кода для разных платформ.

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;
}
1
ответ дан 3 December 2019 в 01:44
поделиться

Чтобы реализовать кроссплатформенную функциональность, требующую поддержки ОС (например, сокеты), вам придется написать код, который просто не будет компилироваться на определенных платформах. Это означает, что ваш объектно-ориентированный дизайн необходимо будет дополнить директивами препроцессора.

Но поскольку вам все равно придется использовать препроцессор, сомнительно, что что-то вроде win32socket (например), которое наследуется от базового класса socket , вообще необходимо или полезно . ОО обычно полезен, когда во время выполнения будут полиморфно выбраны разные функции. Но кроссплатформенная функциональность обычно является проблемой во время компиляции. (например, нет смысла в полиморфном вызове win32socket :: connect , если эта функция даже не компилируется в Linux!) Поэтому может быть лучше просто создать класс socket , который является реализуется по-разному в зависимости от платформы с использованием директив препроцессора.

15
ответ дан 3 December 2019 в 01:44
поделиться

В идеале вы должны сконцентрировать различия на самом низком возможном уровне.
Итак, ваш код верхнего уровня вызывает Foo (), и только Foo () должен внутренне заботиться о том, какую ОС он вызывает.

ps. Взгляните на 'boost', он содержит много вещей для работы с кроссплатформенными сетевыми файловыми системами и т. Д.

2
ответ дан 3 December 2019 в 01:44
поделиться

Второй подход лучше, поскольку он позволяет создавать функции-члены, которые будут существовать только на одной из платформ. Затем вы можете использовать абстрактный класс в независимом от платформы коде и конкретный класс в коде платформы.

Пример:

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();
        }
};
1
ответ дан 3 December 2019 в 01:44
поделиться

Вам не нужно использовать ООП, чтобы быть кроссплатформенным. Кроссплатформенность - это скорее парадигма архитектуры и дизайна.

Я предлагаю изолировать весь код, специфичный для платформы, от стандартного кода, например GUI для сокетов. Сравните их на разных платформах и напишите общий слой или оболочку. Используйте этот слой в своем коде. Создайте библиотечные функции для реализации специфичной для платформы реализации универсального уровня.

Функции, специфичные для платформы, должны находиться в отдельных библиотеках или файлах. В процессе сборки должны использоваться правильные библиотеки для конкретных платформ. В ваш "стандартный" код не должно быть никаких изменений.

4
ответ дан 3 December 2019 в 01:44
поделиться

Как отмечали другие, наследование - неподходящий инструмент для работы. Решение о том, какой конкретный тип использовать в вашем случае, принимается во время сборки, а классический полиморфизм позволяет принять это решение во время выполнения (то есть в результате действий пользователей).

1
ответ дан 3 December 2019 в 01:44
поделиться

Делегирование, как в вашем первом примере или в GMan, работает довольно хорошо, особенно если часть, зависящая от платформы, потребует много членов, зависящих от платформы (например, члены типов, которые существуют только на одной платформе). Обратной стороной является необходимость поддерживать два класса.

Если класс будет проще, без большого количества членов, зависящих от платформы, вы можете просто использовать общее объявление класса и написать две реализации в двух разных файлах .cc (плюс, возможно, третий .cc для независимого от платформы метода реализации). Вам может понадобиться несколько #ifdefs в файле заголовка для нескольких зависящих от платформы членов или членов с типами, зависящими от платформы. Этот способ больше похож на взлом, но с него может быть проще начать. Вы всегда можете переключиться на делегатов, если это выйдет из-под контроля.

1
ответ дан 3 December 2019 в 01:44
поделиться
Другие вопросы по тегам:

Похожие вопросы: