views:

158

answers:

6

I know that the difference between defines and constants is that constants have type, and that between macros and functions, functions are called, and typed, whereas macros are untyped inline. Not so much the difference between structs and classes, but I don't think there is one, besides the public/private default thing (and I'm taking about only C++ here, not C).

Anyways, are there any times that it would be more efficient, beneficial, or, at the very least, cleaner code to use defines/macros/structs than it would be to use the C++ versions, constants, functions, and classes?

Specifically, and because this is only one without a clear difference (at least in the final program) between them, is it ever better to use structs than classes, and if there isn't efficiency-wise, what conventions for using them do you use?

A: 

The more important difference between defines\macros and constants\functions is scope.

Constants should always be a win since the compiler will optimize them to perform as well as defines all the while keeping their clarity.

The case for functions is similar anything you can do with a macro you can do more safely with a function and I have yet to run across a compiler that didn't offer some way to force inlining to make behavior identical to the macro case.

stonemetal
+5  A: 

Typically, in a C++ program I might use a struct for a simple aggregation of data, such as a Point structure that contains an x and a y. I would use a class for objects that have behaviour (member functions) associated with them.

This is just a convention of course, since the compiler treats them almost identically except for the two details mentioned above (default inheritance and default member visibility).

Greg Hewgill
A: 

I would prefer functions and constants to defines and macros, because they are semantically more explicit, so you get more meaningful and controllable feedback by IDEs and compilers.

Homer J. Simpson
A: 

Specifically, and because this is only one without a clear difference (at least in the final program) between them, is it ever better to use structs than classes, and if there isn't efficiency-wise, what conventions for using them do you use?

Structs are better when defining memory blocks. For example the Windows API has a call named CreateDialogIndirect, one of its parameters is a memory block described like this:

[in] Pointer to a global memory object containing a template that CreateDialogIndirect uses to create the dialog box. A dialog box template consists of a header that describes the dialog box, followed by one or more additional blocks of data that describe each of the controls in the dialog box. The template can use either the standard format or the extended format. In a standard template, the header is a DLGTEMPLATE structure followed by additional variable-length arrays. The data for each control consists of a DLGITEMTEMPLATE structure followed by additional variable-length arrays.

This all sounds very complex. Certainly if you would try to allocate a heap allocate buffer of memory and try to fill it according to the description. However, you can use structs to simplify the job:

 struct {
    DLGTEMPLATE t;
    short noMenu;
    short defaultClass;
    short title;
  } templ;

  templ.t.style = style;
  templ.t.dwExtendedStyle = extendedStyle;
  templ.t.cdit = 0;
  // etc...
  HWND hDlg = ::CreateDialogIndirectParam(hInstance,
                                          &templ.t,
                                          hWndParent,
                                          (DLGPROC)DialogProc,
                                          NULL);

I think this is a situation where structs are clearly a better choice than classes. It would work with a class, but that would look very strange, don't you agree?

StackedCrooked
The win32 api is plain c, thus they can't use classes. if the api would have been c++ it would have looked quite different.
Georg Fritzsche
The WinAPI implementers have to use C, but the OP is asking a question about C++. And in C++ I think using a struct is better than using a class for defining memory blocks.
StackedCrooked
+2  A: 

Macros are usually looked down upon (probably quite rightly) because they have no type-safety whatsoever. However, they do come in useful for the kind of things that you can't do directly in C/C++, in particular the stringize operator (#) for making types, variable names and enums into strings to be embedded in the code:

#define STRINGIZE(ARG) #ARG

Macros can also be useful for boilerplate code where you have a lot of repetitive code, eg to insert every member of an enum into a table. It can be much cleaner to use a macro than a function. MFC uses macros in this way to define message handlers, for instance.

the_mandrill
I shudder at the idea of you taking suggestions from MFC, which is often regarded as a monstrosity... but on the whole you're right. +1
rmeador
I pointed that out by way of example -- it's a common enough idiom for reducing the repetition of boilerplate code. It's a syntactic sugar.
the_mandrill
A: 

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.

Eduardo León