Parameterless #defines vs. consts:
As long as the macro is actually replaced by a constant or a variable that doesn't change, both achieve the same thing. But there are some subtle differences if the former statement doesn't hold. Let's use the following class as an example:
class my_class {
explicit my_class(int i);
explicit my_class(const my_class& copy_from);
};
// implementation defined elsewhere, it's irrelevant
If you do the following:
#define MY_CONST_OBJECT my_class(1)
my_class obj1(MY_CONST_OBJECT);
my_class obj2(MY_CONST_OBJECT);
then the constructor of my_class whose parameter is an int is called twice. And the following code is illegal:
my_class& ref1 = MY_CONST_OBJECT;
my_class& ref2 = MY_CONST_OBJECT;
However, if you do the following:
const my_class my_const_object(1);
my_class obj1(my_const_object);
my_class obj2(my_const_object);
then the the constructor of my_class whose parameter is an int is called only once. And the originally illegal code is now legal:
my_class& ref1 = my_const_object;
my_class& ref2 = my_const_object;
Parametric #defines vs. inline functions:
As long as the macro parameters are not expressions, both achieve the same thing. But there are some subtle differences if the former statement doesn't hold. Let's take this macro as an example:
#define MAX(A,B) = ((A) < (B)) ? (A) : (B)
This macro could not take rand() (or any function whose behavior either affects the state of the whole program and/or depends on it) as a parameter, because rand() would be called twice. Instead, using the following function is safe:
template < class _Type >
_Type max( _Type a, _Type b ) { return (a < b) ? a : b ; }
structs vs. classes
There is no real difference between structs and classes other than the former's default access specifier for base classes and members is public and the latter's is private. However, it's uncivilized to declare structs that have methods and, thus, behavior, and it's also uncivilized to declare classes that only have raw data that can be accessed directly.
Declaring a class that is meant to be used as a struct, like this:
class my_class {
public:
// only data members
};
is in bad taste. structs with constructors might have some uses, such as not allowing initialization with trash data, but I would recommend against them as well.