【问题标题】:C: Call class method without explicitly passing `this`?C:调用类方法而不显式传递`this`?
【发布时间】:2015-01-22 11:01:04
【问题描述】:

我想知道预处理器逻辑/宏魔术是否可以让人们在 C(11) 中像在典型的 OO 语言中那样做,即

instance->method(a, b)

instance.method(a, b)

而不是

method(instance, a, b) //instance is 'this'

?

确实这只是一个排序问题,但我很想知道是否有人使用宏实现了类似的单词排序。我更喜欢不必在每个方法调用的客户端代码中将this 作为显式参数传递的想法。因此问题。

【问题讨论】:

  • 当然 - 您可以将函数指针放在结构中。不需要宏。
  • @PaulR 但是您仍然必须明确传递this。这是我试图避免的。用这个事实更新了问题。
  • @PaulR:是的,但是你必须调用obj->funct(obj, a, b),它有一个多余的obj
  • 好的 - 是的 - 我想你可以用一个宏来隐藏它,但那时事情开始变得丑陋了。
  • 我会直言不讳 - 不,没有预处理器魔法可以做到这一点。 1.函数必须传递一个指向实例的指针。 2. 要将宏扩展为您想要的(instance->method(instance, a, b)),它至少需要了解方法、实例和参数。这些必须通过宏参数提供,因为宏不能读取或删除相邻的文本,例如,instance->MACRO(a, b)。因此,最低限度是MACRO(instance, a, b)。但是,由于 instance 被扩展了两次,您的宏可能会做非法的事情:MACRO(ptr++, a, b) 变为 (ptr++)->method((ptr++), (a), (b))

标签: c c-preprocessor preprocessor-directive


【解决方案1】:

使用 GCC,您可以像这样创建宏:

#define MCALL(obj, method, ...) do {\
    typeof(obj) this;\
    this->method(this, ## __VA_ARGS__);\
  } while(0)

但这使用了typeof,这是一个 GCC 扩展。

它适用于无参数,因为它使用 GCC 扩展的 ## 运算符。有关 GCC 如何实现可变参数宏的更多信息,请参阅this manual page

当然,实际上做这样的事情可能是个坏主意,因为您几乎是在重新设计语言本身,从而使其他人更难理解。

【讨论】:

  • 这就是我需要知道的一切,没有道德故事,只有事实 - 谢谢:)
【解决方案2】:

我完全可以看到做这样的事情只是为了好玩。但我会小心在任何将被其他人使用或看到的代码中诉诸这种黑客行为。

“总是像维护你的代码的人是一个疯狂的连环杀手知道你住在哪里一样编码”

努力使用您所使用的语言的约定。

所以要么坚持使用someFunc(obj, param1, param2);,或者如果可以的话,切换到支持所需功能的语言。

【讨论】:

  • 由于您暗示您想要使用这样的功能并且您不清楚您打算在什么样的项目中使用它,所以这种输入可能是有用,虽然它没有严格回答这个问题。如果它使您和您的团队更有效率,并且您愿意牺牲一些可移植性和可维护性,那么请务必使用它。如果它阻止一些浏览 SO 的菜鸟使用这样的骇客,那足以让我高兴。顺便说一句,我看不出我的个人资料图片或您的标题与任何内容(您删除的评论)有什么关系。
  • 我没有暗示过这样的事情。我也没有删除我的评论。不要在与问题不直接相关的“答案”上浪费人们的时间。
  • 你是对的,你说得很清楚“我更喜欢不必在每个方法调用的客户端代码中将其作为显式参数传递的想法。因此问题”。我想从我的角度来看,“请不要”是对“我怎样才能将语言 X 变成看起来像语言 Y?”的答案。如果您不喜欢答案,请忽略它,这就是 SO 通常的工作方式。
【解决方案3】:

如果您不想要“带参数”和“无参数”版本,并且您不介意源代码中的括号不匹配,您可以尝试:

#define MCALL( object, method )  object->method( object

并调用它:

MCALL( mything, setLength ), 57 ) ;
length = MCALL( mything, getLength ) ) ;

但这很丑。

【讨论】:

  • 谢谢,我可以准确地告诉你谁对你的答案投了反对票,因为我刚刚对他们的答案投了反对票。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-07-01
  • 2012-06-25
  • 1970-01-01
  • 1970-01-01
  • 2012-03-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多