我知道基本规则,使用inline
,enum
和const
代替#define
,这不是我想要这个问题的原因。我想知道的是,在C++中使用#define
宏时,什么是可接受的场景,以及如何使用。
请不要张贴问题或链接到“定义与常量”问题或“预处理器与编译器”的问题,我已经通过斯科特·迈耶斯的有效C++,我知道两者的优势。
然而,经过几个小时的网上冲浪,我感觉#define在C++中被视为某种失败者,但我相信在某种情况下,使用它是可以接受的,甚至是可取的。
为了开始工作,我想我能想到的一种方案是创建一个DEBUG
宏,它基于它在代码中启用打印等功能,以实现调试目的。
发布于 2014-02-25 17:57:54
以下是使用#define是一个很好的解决方案的几个场景:
在保留函数签名的同时添加诊断信息:
#ifdef _DEBUG
#define Log(MSG) Log((MSG), __FILE__, __LINE__);
#endif
条件编译和包含保护也是一个很好的例子(没有给出例子,因为您应该理解这一点:)。
样板代码是另一个例子,但这很容易被滥用。将宏用于样板代码的一个很好的例子是Boost.UnitTest中的BOOST_AUTO_TEST_CASE宏(一个更糟糕的例子是将Windows映射到它们的CHAR或WCHAR宏的WinAPI宏集)。
另一个很好的例子是提供编译器特定的关键字和设置:
#if (defined _WIN32) && (defined LIB_SHARED)
# ifdef LIB_EXPORTS
# define LIB_EXPORT __declspec(dllexport)
# else
# define LIB_EXPORT __declspec(dllimport)
# endif /* LIB_EXPORTS */
#else
# define LIB_EXPORT extern
#endif /* _WIN32 && LIB_SHARED */
用法:
// forward declaration of API function:
LIB_EXPORT void MyFunction(int);
发布于 2014-02-25 15:25:18
调试/发布或跨平台代码的简单设置。下面是我的程序示例:
void Painter::render()
{
if (m_needsSorting)
{
_sort();
}
for (GameObject* o : m_objects)
{
o->render();
#ifdef _DEBUG
o->renderDebug();
#endif
}
}
对于win/ios,还有一个:
#ifdef _WIN32
#include "EGL/egl.h"
#include "GLES2/gl2.h"
#include <Windows.h>
#ifdef _ANALYZE
#include <vld.h>
#endif
#else // IOS
#import <Availability.h>
#import <UIKit/UIKit.h>
#import <GLKit/GLKit.h>
#import <Foundation/Foundation.h>
#endif
另一件事是库:
#ifdef VECTRY_INLINE
#define vinline inline
#else
#define vinline
#endif
还有一些有用的东西,比如:
#define MakeShared(T) \
class T; \
typedef shared_ptr<T> T##Ptr
发布于 2014-02-25 16:52:39
有时,您希望无需重复永不结束的样板,或不必使用另一种语言来生成代码。From time to time,模板是不够的,您最终将使用Boost.Preprocessor来生成代码。
宏是“必需的”的一个例子是Boost.TTI (类型特征自省)。底层机制以某种方式滥用语言来创建几个强大的元函数,但需要大量的样板。例如,宏BOOST_TTI_HAS_MEMBER_FUNCTION
生成一个matefunction,它检查一个类是否具有给定的成员函数。这样做需要创建一个新类,并且在没有宏的情况下不能很短(解决问题的非宏解决方案的示例here)。
有时,您还需要使用X-macros来生成代码。在编译时绑定东西是非常有用的。到目前为止,我不确定它们是否可以完全被取代,但不管怎样,你可以找到一些非常有趣的应用程序here的例子。
总而言之,宏可以是生成代码的强大工具,但需要谨慎使用。
https://stackoverflow.com/questions/22007222
复制相似问题