定义类似关键字的宏只是为了提高代码的可读性

Defining keyword-like macros just for improving code readablity

本文关键字:高代码 代码 可读性 关键字 定义      更新时间:2023-10-16

如果定义类似关键字的宏可以提高代码的可读性,这是错误的吗?

例如IMPLICIT宏:

#define IMPLICIT /* IMPLICIT constructor(parameters...); */
struct X
{
    explicit X();
    IMPLICIT X(int i);
    IMPLICIT X(std::sting s);
    explicit X(const char* ch);
};

代替:

struct X
{
    explicit X();
    X(int i);
    X(std::sting s);
    explicit X(const char* ch);
};

考虑:不管代码的可读性如何,IMPLICIT宏的定义可以简单地禁用所有隐式构造函数或…,以便将来维护。

编辑:我的例子并不重要,我的问题不是特定于它,我删除了block宏的例子。

定义类似关键字的宏只是为了提高代码的可读性

我认为可以接受。但就像马可说的,这是相当主观的。


我认为一个宏增强可读性的例子是c++和NOTHROW。奇怪的是,指定throw()意味着函数不会抛出;与throw (SomeException)相反,这意味着函数可以抛出异常。当它不抛出时,声明throw()没有什么直观的。

Stack Overflow上有很多关于它的讨论:

  • c++ throw装饰有什么用?
  • 在函数签名中抛出关键字 void func() throw(type)的意义是什么?
  • vc++ 2008/2010: throw()还是__declspec(nothrow)是更好的选择?

Microsoft定义了IN, OUTINOUT,以帮助可读性和可用性。宏修饰函数参数,并定义为空。例如,您可能会看到(我手边没有特定的Microsoft示例):

// Process foo. Reuse baz if possible; reallocate if needed and return size.
// Return TRUE/FALSE as success/failure. Return an error code if result is FALSE.
int FooBarBaz(IN char* foo, IN int flen, INOUT char** baz, INOUT int* blen, OUT int* err);

Related:宏有助于抽象平台差异。例如,从共享对象(Unix和仿制品)或动态链接库(Windows)导出函数。


Related:宏有助于抽象配置差异。例如,ASSERT在调试和发布配置中的含义或实现。


相关:劫持关键字可能会有所帮助。例如,在测试过程中,将c++的protectedprivate重新定义为public是有帮助的,这样就可以针对通常不可访问的方法编写测试用例。

如前所述,宏不能增强可读性。有些人可能想知道BLOCKIMPLICIT是什么意思,认为它们执行一些特殊的功能,而实际上它们没有。它似乎更适合于注释或重构。在像Visual Studio这样的ide中,您可以折叠代码行(隐藏/显示它们)或将它们分组到文档块中(即#REGION)。不做任何事情的宏只是在代码中添加噪音。

我最好的宏是一个日志宏:

#define SYSTEM_FAILURE(code, comment) 
{ 
    System_Failure(code, comment, __FILE__, __FUNCTION__, __LINE__); 
}

宏是插入遇到故障的文件名、函数名和行号的最简单方法。

除了这个宏,我们的商店中没有其他宏。

很难找到好的例子,其中使用宏来提高可读性是无法避免的。

这是我能想到的最好的例子(来自Linux内核):

#define FIELD_SIZEOF(t, f) (sizeof(((t*)0)->f))

的例子:

struct book {
  char title[100];
  char author[100];
};
// ...
printf("%lun", FIELD_SIZEOF(struct book, title)); // prints 100

(我不知道在c++中是否可以避免这个宏)

除此之外,我认为当宏用于代码生成以消除样板代码时,它们有时可以提高可读性。