183 votes

Lorsque le C++ macros bénéfique?

Le préprocesseur C est à juste titre craints et méprisés par le C++ de la communauté. Dans bordées de fonctions, consts et les modèles sont généralement plus sûrs et de meilleure alternative à un #define.

La macro suivante:

#define SUCCEEDED(hr) ((HRESULT)(hr) >= 0)

est en aucun cas supérieure au type de coffre-fort:

inline bool succeeded(int hr) { return hr >= 0; }

Mais elles n'ont leur place, veuillez énumérer les utilisations que vous trouver pour les macros que vous ne pouvez pas faire sans le préprocesseur.

S'il vous plaît mettre à chaque cas d'utilisation dans une autre réponse, de sorte qu'il peut être voté, et si vous savez comment atteindre l'une des réponses sans le preprosessor souligner comment, dans cette réponse, les commentaires.

130voto

Frank Szczerba Points 2767

Comme emballages pour les fonctions de debug, de transmettre automatiquement des choses comme __FILE__, __LINE__,, etc:

#ifdef ( DEBUG )
#define M_DebugLog( msg )  std::cout << __FILE__ << ":" << __LINE__ << ": " << msg
#else
#define M_DebugLog( msg )
#endif

94voto

jdmichal Points 6283

Les méthodes doivent toujours être complète, code compilable; les macros peuvent être des fragments de code. Ainsi vous pouvez définir un foreach macro:

#define foreach(list, index) for(index = 0; index < list.size(); index++)

Et de l'utiliser ainsi:

foreach(cookies, i)
    printf("Cookie: %s", cookies[i]);

61voto

Kevin Points 7334

Fichier d'en-tête des gardes nécessitent des macros.

Existe-il des autres domaines qui nécessitent des macros? Pas beaucoup (le cas échéant).

Existe-il d'autres situations qui bénéficient de macros? OUI!!!

Un endroit où je utiliser des macros est très répétitif code. Par exemple, lors de l'emballage de code C++ pour être utilisé avec d'autres interfaces.NET, COM, Python, etc...), j'ai besoin d'attraper différents types d'exceptions. Voici comment je fais:

#define HANDLE_EXCEPTIONS \
catch (::mylib::exception& e) { \
    throw gcnew MyDotNetLib::Exception(e); \
} \
catch (::std::exception& e) { \
    throw gcnew MyDotNetLib::Exception(e, __LINE__, __FILE__); \
} \
catch (...) { \
    throw gcnew MyDotNetLib::UnknownException(__LINE__, __FILE__); \
}

Je dois mettre ces captures dans chaque fonction wrapper. Plutôt que de taper le plein blocs catch à chaque fois, il me suffit de taper:

void Foo()
{
    try {
        ::mylib::Foo()
    }
    HANDLE_EXCEPTIONS
}

Cela aussi rend la maintenance plus facile. Si jamais j'ai à ajouter un nouveau type d'exception, il n'y a qu'un seul endroit où j'ai besoin de l'ajouter.

Il y a d'autres exemples utiles: plusieurs incluent l' __FILE__ et __LINE__ macros du préprocesseur.

De toute façon, les macros sont très utiles lorsqu'ils sont utilisés correctement. Les Macros ne sont pas mal dans leur utilisation abusive qui est mal.

54voto

David Thornley Points 39051

Principalement:

  1. Inclure des gardes
  2. Compilation conditionnelle
  3. Reporting (macros prédéfinies comme __LINE__ et __FILE__)
  4. (rarement) la Duplication de code répétitif des motifs.
  5. Dans votre concurrent du code.

50voto

Andrew Stein Points 6344

À l'intérieur de la compilation conditionnelle à surmonter les problèmes de différences entre les compilateurs:

#ifdef ARE_WE_ON_WIN32
#define close(parm1)            _close (parm1)
#define rmdir(parm1)            _rmdir (parm1)
#define mkdir(parm1, parm2)     _mkdir (parm1)
#define access(parm1, parm2)    _access(parm1, parm2)
#define create(parm1, parm2)    _creat (parm1, parm2)
#define unlink(parm1)           _unlink(parm1)
#endif

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X