问题描述:

I've got to add a bunch of members to a class. I would like to add a macro such as this:

#define MEMBER(TYPE,NAME) \

private: TYPE m_##NAME; \

public: TYPE get##NAME() const { return m_##NAME; } \

public: void set##NAME(TYPE in##NAME) { m_##NAME = in##NAME; }

and then use it to add the members to the class:

class foo {

MEMBER(std::string, OutputDir);

MEMBER(int, MaxIterations);

MEMBER(double, OptimizationCutoff);

// And a couple dozen more members...

public:

// The rest of the class declarations

};

The intend is obviously to shortcut multiple instances of code like this, 3 lines for each of the multitude of class members:

private: std::string m_OutputDir;

public: std::string getOutputDir() const { return m_OutputDir; }

public: void setOutputDir(std::string inOutputDir) { m_OutputDir = inOutputDir; }

Are there any consideration against coding like that?

网友答案:

Firstly, I'd point out an observation. The macros you've defined here seem to be completely useless. I get what you're trying to do -- with one line of code declare a member variable and simple getter and setter methods.

I would counter: if you're just exposing these member variables with simple getters & setters, why not just make the member variable public and be done with it?

Are there any consideration against coding like that?

Yes, all the usual concerns about Evil misuse of macros. Let's go through a few as they pertain here.

You are creating a secret language that only you will know.

Code that looks like this:

class foo {
    MEMBER(std::string, OutputDir);
    MEMBER(int, MaxIterations);
    MEMBER(double, OptimizationCutoff);
    // And a couple dozen more members...
    public:
    // The rest of the class declarations
};

at a glance might be somewhat obvious in it's construction, but there are many details that are obscured when it comes time to maintain or extend either foo, one of the members, or the macro itself.

For example, in just glancing at this I get the idea that you are declaring a member OutputDir, but there's really no indication if it's a data member or a member function. If it's a member function, what is the return type? What are the parameters? How would I declare a member function template? What are the template parameters?

You have built a syntax here that might save a keystroke or two when first typing the code, but can generate hours and hours of frustration and head-banging when someone needs answers to any of these questions. Since it isn't documented or supported by anybody but you, your macros end up being akin to a secret language that only you know.

Macros are difficult to debug

When degugging code that uses a macro, you see the substituted text -- not the macro or how it was called. This can be very confusing.

Macros have no namespace

Macros are a brute-force text substitution tool. They do not respect any namespace or scope, and are universally applied everywhere they are defined and invoked. This steps around the C++ type system completely and lets your write code that would otherwise evoke an error.

Macros have strange and unintended side effects and are applied in places you didn't expect.

A common example is the definition of the min and max macro by VisualStudio, which clobbers the functions by the same name in the Standard Library. Side effects can be bizarre and, as mentioned, very difficult to debug.

相关阅读:
Top