Вопрос о передовых методах и макросах из книги «Стандарты кодирования C ++» - PullRequest
2 голосов
/ 08 января 2011

Из статьи Херба Саттера и Андрея Александреску «Стандарты кодирования C ++», пункт 16. Избегайте макросов в рамках исключений для этого руководства, которое они написали:

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

У меня проблемы с пониманием, что именно они имеют в виду. Как вы можете использовать альтернативные реализации без использования директив условной компиляции #ifdef? Может ли кто-нибудь привести пример, чтобы проиллюстрировать, что предлагается в предыдущем абзаце?

Спасибо

Ответы [ 2 ]

4 голосов
/ 08 января 2011

Они означают, что вы должны абстрагировать свой код от системно-зависимой части с помощью абстрактных базовых классов и использовать компиляцию условий только в момент создания экземпляра.

class SystemAgnosticInterface
{
public:
    virtual ~SystemAgnosticInterface() {}
    virtual void doStuff() = 0;
};

В таком случае вы можете, например, иметь конкретные реализации интерфейса для Windows и Linux (каждая из которых будет включена в компиляцию только для соответствующей платформы), например:

SystemAgnosticInterface *createFoo()
{
#ifdef _WIN32
    return new WindowsImplementation;
#else
    return new LinuxImplementation;
#endif
}

int main()
{
    SystemAgnosticInterface *foo = createFoo();
    foo->doStuff(); // No conditional compilation here
    delete foo;
}

Это явно упрощенный пример кода, но я надеюсь, вы поймете суть: дело не в том, чтобы полностью избегать #ifdef, просто в том, что они не должны загромождать каждую часть вашего кода.

2 голосов
/ 08 января 2011

Для функций, не являющихся членами:

//implementation!

#ifdef _WIN32
    void EatWindow(Food &) {}
    void DrinkWindow(Beverage &) {}
    void SleepWindow(Bed &) {}
#else
    void EatLinux(Food &) {}
    void DrinkLinux(Beverage &) {}
    void SleepLinux(Bed &) {}
#endif

//interface

#ifdef _WIN32
    #define Eat(food)       EatWindow(food)
    #define Drink(beverage) DrinkWindow(beverage)
    #define Sleep(bed)      SleepWindow(bed)
#else
    #define Eat(food)       EatLinux(food)
    #define Drink(beverage) DrinkLinux(beverage)
    #define Sleep(bed)      SleepLinux(bed)
#endif

Используйте интерфейсы Eat(), Drink() и Sleep() во всей вашей программе, будь то Windows или Linux. Никакой условной проверки нигде!

...