Preprocessing occurs before the code is compiled. It's appropriate in cases like the following
#ifdef WIN32
#include <something.h>
#elseif LINUX
#include <somethingelse.h>
#endif
Obviously including header files you want done at compilation time not runtime. We can't do this with variables.
On the other hand. With C++ it is good practice and greatly encouraged to replace constant expressions like the following example
#define PI 3.141592654
with
const double PI=3.141592654;
The reason is that you get proper typecasting and datatype handling.
Also
#define MAX(x,y) (x) > (y) ? (x) : (y)
Is not very nice because you can write
int i = 5
int max = MAX(i++, 6);
The preprocessor (if I'm not wrong) would replace that with
int max = (i++) > (y) ? (x++) : (y);
Which is clearly not going to give the intended result.
Instead, MAX should be a function (not a macro). If it's a function it can also provide the type in the parameter.
I have seen the preprocessor used for all sorts of interesting things. Like language keyword declaration. It can aid in readability in this case.
In short, use the preprocessor for things that must happen at compile type such as conditional includes directives. Avoid using it for constants. Avoid macros and instead use functions where possible.