4

我正在尝试编写一个宏来协助 C 中的面向对象编程。当我将类信息存储在一个常量结构中时,我需要创建一个执行以下操作的宏:

  • 取对象的类型(解除引用的指针的类型)
  • 追加_info以获取所需的 classInfo 结构的名称
  • 获取该符号的地址,以便将其传递给函数
  • destroyObject使用指向类结构和对象本身的指针调用函数

一个例子:

queue_t* p = NULL;
delete(p);

delete应扩展为:

destroyObject(&(queue_t_info), p);

我尝试使用此宏,但无法开始工作:

#define delete(X) (destroyObject(&(typeof(*X)##_info), X))

我在 typeof 部分无法正常工作时遇到问题。

4

2 回答 2

7

typeof不是宏,它是语言构造,它由编译器扩展,而不是预处理器。由于预处理在编译之前进行,宏无法访问typeof结果。

delete(p)的扩展为:(destroyObject(&(typeof(*p)_info), p))。(您可以通过-Egcc 标志看到它)

于 2013-02-26T11:36:15.573 回答
2

我意识到我试图做的事情是不可能的——C 预处理器不会解析和符号化代码,因此它不知道变量是哪种类型。

为了解决这个问题,我还需要将类型传递给删除函数。这并不理想,因为它引入了由于类型不匹配而导致的常见错误来源。如果程序员传递了一个指向对象 A 的指针,但在删除函数中指定了对象 B,则会调用错误的析构函数。为了解决这个问题,我在宏中添加了类型检查,以便为任何不匹配的类型生成编译器警告。

#define typecheck(type,x) \
({  type __dummy; \
typeof(x) __dummy2; \
(void)(&__dummy == &__dummy2); \
})

#define delete(P, X) (destroyObject(&(X##_info), P), typecheck(X, *P))
#define new(X, ...) (createObject(&(X##_info), ##__VA_ARGS__))

宏的正常用法:

queue_t* p = new(queue_t);
delete(p, queue_t);

但是使用错误的类型:

queue_t* p = new(queue_t);
delete(p, int);

导致编译器警告:

Comparison of distinct pointer types ('int *' and 'typeof (*p) *' (aka 'queue_t *'))
于 2013-02-26T11:40:42.283 回答