What's the difference, in different ways, between define / macroros / structs and consts / funcs / classes? (C ++)

I know that the difference between definitions and constants is that constants are of type, and between macros and functions - functions are called and typed, whereas macros are untyped internally. Not much difference between structs and classes, but I don't think there is one other than the default public / private thing (and I'm only dealing with C ++ here, not C).

Anyway, is there ever any more efficient, useful, or at least cleaner code for using define / macroros / structs than using C ++ versions, constants, functions and classes

In particular, and since this is only one with no explicit difference (at least in the last program) between the two, is it better to use structs than classes, and if there is no efficiency, what conventions do you use to use them?

+2


source to share


6 answers


Typically, in a C ++ program, I can use struct

for simple data aggregation, such as a structure Point

containing x

and a y

. I would use class

for objects that have behavior (member functions) associated with them.



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

+5


source


Macros are usually viewed from top to bottom (probably quite right) because they don't have any type safety. However, they are useful for things that you cannot do directly in C / C ++, in particular the stringize (#) operator for creating types, variable names, and enumerations into strings that must be embedded in code:

#define STRINGIZE(ARG) #ARG

      



Macros can also be useful for template code where you have a lot of repetitive code, such as inserting each element of an enumeration into a table. It might be much cleaner to use a macro than a function. For example, MFC uses macros to define message handlers.

+2


source


The more important the distinction between parameters \ macros and constants \ functions is scope.

Constants should always be a win as the compiler will optimize them for execution, and it also defines everything while maintaining its clarity.

The case for functions is similar to anything you can do with a macro, which you can do more safely with a function, and I have yet to run into a compiler that hasn't offered any way to force nesting to make the behavior identical to the macro case.

0


source


I would prefer functions and constants for definitions and macros because they are semantically more explicit, so you get more meaningful and controlled feedback with IDEs and compilers.

0


source


In particular, and since it is only one with no apparent difference (at least in the last program) between them, is it better to use structs than classes, and if not in terms of efficiency, which ones are you using using them?

Structures are better at defining blocks of memory. For example, the Windows API has a call named CreateDialogIndirect, one of its parameters is a block of memory, described as follows:

[in] Pointer to a global memory object containing the template that CreateDialogIndirect uses to create in the dialog box. A dialog box template consists of a title that describes the dialog box, followed by one or more additional data blocks that describe each of the controls in the dialog box. The template can use either standard format or extended format. In the 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 complicated. Of course if you try to allocate a bunch of allocated memory buffer and try to fill it as described. However, you can use structs to make things easier:

 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 better than classes. This will work with the class, but it will look very strange, don't you agree?

0


source


Parameter #define

vs. const

s:

As long as the macro is actually replaced by a constant or variable that does not change, both achieve the same. But there are some subtle differences if the previous statement fails. The following class can be used as an example:

class my_class {
    explicit my_class(int i);
    explicit my_class(const my_class& copy_from);
};

// implementation defined elsewhere, it 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 a constructor my_class

that has a parameter is int

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 a constructor my_class

whose parameter is int

called only once. And the originally illegal code is now legal:

my_class& ref1 = MY_CONST_OBJECT;
my_class& ref2 = MY_CONST_OBJECT;

      

Parametric #define

vs. inline

functions:

As long as macros are not expressions, both achieve the same. But there are some subtle differences if the previous statement fails. Let's take this macro as an example:

#define MAX(A,B) = ((A) < (B)) ? (A) : (B)

      

This macro cannot accept rand()

(or any function whose behavior affects the state of the entire program and / or depends on it) as a parameter, because it rand()

will be called twice. Instead, using the following function is safe:

template < class _Type >
_Type max( _Type a, _Type b ) { return (a < b) ? a : b ; }

      

struct

against. class

es

There is no real difference between struct

and class

es other than the former default access specifier for base classes, and members public

and the latter are private

. However, it is uncivilized to declare struct

that have methods and therefore behavior, and it is also uncivilized to declare class

es that have only raw data that can be accessed directly.

A declaration class

that is supposed to be used like struct

, for example:

class my_class {
public:
    // only data members
};

      

is in bad taste. struct

with constructors may have some uses, such as not allowing initialization with garbage data, but I would recommend against them as well.

0


source







All Articles