【问题标题】:Question about best practices and Macros from the book 'C++ Coding Standards'关于“C++ 编码标准”一书中的最佳实践和宏的问题
【发布时间】:2011-01-08 12:38:17
【问题描述】:

来自 Herb Sutter 和 Andrei Alexandrescu 的“C++ 编码标准”,第 16 项:在例外情况下避免宏,他们为此指南编写了:

对于条件编译(例如, 系统相关部分),避免 用#ifdefs 乱扔代码。 相反,更喜欢组织这样的代码 使用宏驱动 一个的替代实现 通用接口,然后使用 整个界面。

我无法准确理解它们的意思。如何在不使用 #ifdef 条件编译宏指令的情况下驱动替代实现?有人可以提供一个例子来帮助说明上述段落的建议吗?

谢谢

【问题讨论】:

    标签: c++ macros coding-style


    【解决方案1】:

    他们的意思是你应该通过使用抽象基类从系统相关部分抽象你的代码,并且只在实例化点使用条件编译。

    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,只是它们不应该把你代码的每一部分都弄得乱七八糟。

    【讨论】:

    • 虽然接口不必是虚拟的 - 您可以改为使用 #ifdef ed typedef,用于每个系统上的不同类,它们都实现了一个通用 API。
    【解决方案2】:

    对于非成员函数:

    //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。其他任何地方都没有条件检查!

    【讨论】:

    • 对于接口的语法似乎有点不对劲。您的意思是对 Eat()、Drink()、Sleep() 使用 #define 吗?或者您可能打算包含花括号。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-17
    • 2021-06-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多