gor*_*rba 18 c++ macros c-preprocessor
我知道基本的规则,使用inline,enum而const不是#define,这不是我追求这个问题.我想知道的是#define在C++中使用宏以及如何使用宏的可接受场景.
请不要发布问题或链接到"define vs const"问题或"预处理器与编译器",我已经通过了Scott Meyers的Effective C++,我知道一个优于另一个的优点.
然而,经过几个小时的网上冲浪,我觉得#define被认为是C++中的某种弱者,但我确信必须有一个案例,使用它可以接受甚至是可取的.
为了推动这个问题,我猜想我可以想到的一个场景是创建一个DEBUG基于它的宏,它可以打印所有代码以及用于调试目的的所有内容.
utn*_*tim 11
以下是使用#define是一个很好的解决方案的一些场景:
在保留功能签名的同时添加诊断信息:
#ifdef _DEBUG
#define Log(MSG) Log((MSG), __FILE__, __LINE__);
#endif
Run Code Online (Sandbox Code Playgroud)
条件编译和包含警卫也是一个很好的例子(没有给出一个例子,因为你应该理解这个:)).
Boilerplate代码是另一个例子,但这很容易被滥用.使用宏作为样板代码的一个很好的例子是Boost.UnitTest中的BOOST_AUTO_TEST_CASE宏(更糟糕的例子是将Windows API映射到其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 */
Run Code Online (Sandbox Code Playgroud)
用法:
// forward declaration of API function:
LIB_EXPORT void MyFunction(int);
Run Code Online (Sandbox Code Playgroud)
调试/发布或跨平台代码的简单设置.这是我的程序示例:
void Painter::render()
{
if (m_needsSorting)
{
_sort();
}
for (GameObject* o : m_objects)
{
o->render();
#ifdef _DEBUG
o->renderDebug();
#endif
}
}
Run Code Online (Sandbox Code Playgroud)
还有一个对于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
Run Code Online (Sandbox Code Playgroud)
另一件事是图书馆:
#ifdef VECTRY_INLINE
#define vinline inline
#else
#define vinline
#endif
Run Code Online (Sandbox Code Playgroud)
以及一些有用的东西:
#define MakeShared(T) \
class T; \
typedef shared_ptr<T> T##Ptr
Run Code Online (Sandbox Code Playgroud)
C++中为数不多的有用案例之一包括警卫:
// A.h
#ifndef _A_H_
#define _A_H_
class A
{ /* ... */ };
#endif /* _A_H_ */
Run Code Online (Sandbox Code Playgroud)
有时,您希望生成代码而无需重复无休止的样板,或者不必使用其他语言来执行此操作.有时,模板不够用,最终您将使用Boost.Preprocessor生成代码.
宏是"必需"的一个例子是Boost.TTI(类型特征内省).底层机制以某种方式滥用语言来创建一些强大的元函数,但需要大量的样板.例如,宏BOOST_TTI_HAS_MEMBER_FUNCTION生成一个matefunction,用于检查类是否具有给定的成员函数.这样做需要创建一个新类,如果没有宏,就不能做空(这里有解决问题的非宏解决方案示例).
有时候您需要使用X-macros来生成代码.在编译时绑定东西非常有用.我不确定它们是否可以在今天完全替换,但无论如何,你可以在这里找到一些非常有趣的应用程序示例.
总而言之,宏可以是生成代码的强大工具,但需要谨慎使用.
我认为当C被引入时,C并没有使用consts,所以#defines提供常量值的唯一方法也是如此.但后来#define并没有太多使用,因为consts取而代之(或者更好的说法,我们可以说consts更容易使用).但我会说包括警卫仍然是他们使用的一个领域.它们被使用,因为您的代码更具可读性.
头部包含防护是一个你不能使用consts的区域
而例如:
#ifndef GRANDFATHER_H
#define GRANDFATHER_H
struct foo {
int member;
};
#endif /* GRANDFATHER_H */
Run Code Online (Sandbox Code Playgroud)
您还可以检查为什么有人会使用#define来定义常量?
还有一点要补充,#defines不要考虑范围,所以没有办法创建一个类范围的命名空间,而const变量可以在类中定义.(我知道你知道区别但是想要添加它,因为它很重要.)
还要显示使用#define的一个示例:
static double elapsed()
{ ... }
#define ELAPSED '[' << std::fixed << std::setprecision(2) << elapsed() << "] "
// usage:
for (vector<string>::iterator f = files.begin(); f != files.end(); f++) {
cout << ELAPSED << "reading file: " << *f << '\n';
process_file(*f);
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1056 次 |
| 最近记录: |