In the use of constants the two answers above are correct, however #define
is not limited to that use alone. Another example of the use of #define
is macros.
Macros
Macros are preprocessor-utilised pieces of code, and they work exactly like other #define
declarations in that regard. The preprocessor will literally swap out the occurrence of your defined symbol with the code of the macro. An example:
#define HELLO_MAC do{ std::cout << "Hello World" << std::endl; }while(false)
int main(int argc, char** argv)
{
HELLO_MAC;
}
That will literally swap out the HELLO_MAC
symbol with the code I declared. If it were a constant it would do the exact same thing. So you can think of #define
s for constants as a particular kind of macro.
With macros you can also pass parameters, and it is especially useful I find for enforcing logging/exception policies over code.
For example
#define THROW_EXCEPT( ex_type, ex_msg ) /
do{ throw ex_type( buildExString( (ex_msg), __LINE__, __FILE__ ) ); }while(false)
...
// somewhere else
THROW_EXCEPT( std::runtime_error, "Unsupported operation in current state" );
That code allows me to ensure that everyone logs with the line of the file that threw the exception.
Templates are often a better choice instead of macros, but I cannot use template functions for this example because I need to use the __LINE__
and __FILE__
functions from the place of the throw, not from the location of the template function.
Where should you not use macros? Anywhere you can use something else. Macros, like any #define
are preprocessed, so the compiler does not see them at all. This means that there is never any symbols created for HELLO_MAC
or THROW_EXCEPT
, and so they cannot be seen in a debugger. They can also be confusing if you get compile errors, especially if they are long macros.