質問

I have various class Case0, Case1, Case2, etc. and I would like to switch between them using some preprocessor #defines. They all share the same interface (the same public methods) and I could use OOP but I'd prefer to use preprocessor directives.

For now I have something like:

#define CASECLASS Case0
//#define CASECLASS Case1
//#define CASECLASS Case2

#define CASE 0

class Main {
public:
   CASECLASS *mycase;

   Main() {

       mycase = new CASECLASS();

       if(CASE==0) {
           mycase->foo();
           // something else
       }
       if(CASE==1) {
           mycase->foo();
           // something else
       }
   }
}

In this way every time I have to switch I have to change the defines CASECLASS and CASE. I'm wondering if there is a cleaner method.

Edit:

I don't want to use OOP because the different classes use different libraries. This can affect compile time, and they are platform dependent. I think that preprocessor directives are a better bet here.

役に立ちましたか?

解決

If they all share the same interface, why do you even need to switch among them? Here's some better ideas.

First one: have the preprocessor magic in one place. Put this in a header:

#if defined(PLATFORM_ONE)
#include "platform_one/implementation.hpp"
typedef PlatformOneImplementation TheClass;
#elif defined(PLATFORM_TWO)
#include "platform_two/implementation.hpp"
typedef PlatformTwoImplementation TheClass;
#else
#error No implementation available.
#endif

This would be the only place in your project that uses the preprocessor. Everything else just uses TheClass and nothing platform-dependent. If it's dependent, then the implementation class should hide it.

And as mentioned above, use project configurations to switch.

Here's an even better option. Put this in a header:

class TheClass {
public:
  TheClass();
  ~TheClass();
  // Public stuff goes here.
private:
  struct Impl;
  std::unique_ptr<Impl> pimpl;
};

Then you have one .cpp file per platform and use project configurations to only compile the right one:

// platform_one/implementation.cpp
struct TheClass::Impl {
  PlatformSpecificStuff stuff;
  MoreStuff more;
};
TheClass::TheClass() : pimpl(new Impl) {}
TheClass::~TheClass() {}
// Implementation of public functions here.

Both of these options are infinitely better than littering your code with preprocessor switches.

他のヒント

My typical suggestion in this situation is to put the differing code in different source files, and use your build tool to select which one of those source files gets built at build time.

You can certainly get it to work with preprocessor tricks. But the preprocessor is an error-prone extra-language hack that can make your source code much harder to read and much harder to maintain. Its best to avoid using it where possible.

The following code must work :

    #ifdef CASE1
    class1
    {
    };
    #endif

    #ifdef CASE2
    class2
    {
    };
    #endif

    #ifdef CASE3
    class3
    {
    };
    #endif

And use Project Configurations.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top