在 C++ 中模拟嵌套函数

Posted

技术标签:

【中文标题】在 C++ 中模拟嵌套函数【英文标题】:Simulating nested functions in C++ 【发布时间】:2011-07-18 09:11:03 【问题描述】:

在 C 中,以下代码在 gcc 中有效。

int foo( int foo_var )

 /*code*/
  int bar( int bar_var )  
  
    /*code*/
    return bar_var;
  
  return bar(foo_var);

如何使用 gcc 编译器在 C++ 中实现与嵌套函数相同的功能?如果这似乎是一个初学者问题,请不要介意。我是这个网站的新手。

【问题讨论】:

如果您在 C 中需要此功能,那么您可能是在滥用该语言。即使不是,至少在主要编译器上工作的解决方案,如果不是完全标准的东西,将比基本上非常罕见的编译器特定扩展更可取。 +1 哇,我不知道这是可能的!谢谢你让我学到新东西^^! 并且...到 CW 的转换被破坏(6 个相同的编辑触发了它)。这是否已经是我可以投票支持的元数据已知问题? @Ben:转换似乎是由 5 个不同的编辑触发的(尽管他们的更改基本相同,但这很重要)。然而,修订历史中还有一个奇怪的地方,它没有多大意义。见:meta.stackexchange.com/questions/83772/… C++ can we have functions inside functions? 的可能副本。那里的答案还包括如何做。 【参考方案1】:

我知道这个帖子很旧。但是 C++11 的解决方案是编写 lambdas 并在需要时调用它们

【讨论】:

【参考方案2】:

C++ 中不允许使用局部函数,但在局部类中允许使用局部类和函数。所以:

int foo( int foo_var )

 /*code*/
  struct local 
  
    static int bar( int bar_var )  
    
      /*code*/
      return bar_var;
    
  ;
  return local::bar(foo_var);

在 C++0x 中,您还可以选择使用 lambda 语法创建函子。这在 C++03 中稍微复杂一些,但如果您不需要捕获变量,这仍然不错:

int foo( int foo_var )

 /*code*/
  struct bar_functor
  
    int operator()( int bar_var )  
    
      /*code*/
      return bar_var;
    
   bar;
  return bar(foo_var);

【讨论】:

+1。我有时会使用局部结构来替代嵌套函数! 在成员函数上缺少static @aschepler:第一个,是的。谢谢,现已修复。 只是为了迂腐——你需要在 struct local 的右大括号后加一个分号。你至少在我的编译器上做(Borland/CodeGear)。 @TheMask:您可以将数据成员添加到类中。要在函数和嵌套函数之间共享数据,您可以将它们放在类中并让外部函数通过实例访问它们,或者将引用放在类中。第一个称为hoisting,它是C# 编译器创建闭包的方法。第二个是 C++11 在创建 lambda 时更喜欢的内容。自然地,使用 C++ 引用捕获闭包(使用或不使用 lambda 语法)您必须担心对象的生命周期。【参考方案3】:

使用局部函子

#define lambda(return_type, function_body) \
struct  return_type operator () function_body 


int main ()

    lambda(int, (int x, int y)  return x > y ? x : y;  ) maxFunc;
    int m = maxFunc(1,2); //=> 2
    ...

【讨论】:

+1 我真的很喜欢你的“C lambda”的简单性。但如果提问者谈论“从 C 到 C++”,建议使用 C++ 风格(C++11 lambdas)而不是宏 :)【参考方案4】:

最接近嵌套函数的构造是 C++11 lambda。

void SomeFunction(int x)

    int var = 2;
    auto lambda = [&] (int param) -> int  return var + param; ;

    printf("var + x = %d\n", lambda(x));

Lamdas 允许使用外部范围的变量([&] 指定通过引用自动捕获外部范围的所有变量)。不使用外部作用域(使用 [])的任何变量的 lambda 可以转换为相同类型的函数指针,因此可以传递给接受函数指针的函数。

【讨论】:

【参考方案5】:

把你的函数变成一个函子Herb Sutter suggests in this article

【讨论】:

这是一个很好的链接,但你真的可以通过 演示它 as Ben did in his answer. 仅链接的答案......有点恶心。无论链接有多好,如果它断开,答案就会变得毫无价值。 @GMan:我说我投了反对票吗? @Prasoon:如果您对改进答案不感兴趣,请不要要求对否决票进行解释。很久以前投票反对它的人就会继续前进 - 你得到的任何解释都将来自像我这样的第 3 方。如果你只是为了获得同情,那我就不应该打扰。 @Shog9:我说你做了吗? (不;事实上,我非常小心暗示这显然是白费力气。) 我没有投反对票,但这个答案显然是错误的。 (我的第一个代码 sn-p 是演示,它不是函子,它完全包含在外部函数中) s/need to/should/ 答案为真,这就是为什么我既不上也不下否决它。 @Prasoon:+1 以获得完全正确的答案。 @GMan,@Shog9:我不知道谁对此投了反对票,但我怀疑其他两个答案的反对票来自同一个沉默的 killer 反对票。【参考方案6】:

您可以尝试使用 boost::phoenix(v2 是精神的子包,v3 是在 svn/trunk 中,因为它是自己的包,应该在 1.47 中)

#include <boost/spirit/include/phoenix.hpp>
#include <boost/function.hpp>

using namespace boost::phoenix::arg_names;

int foo( int foo_var )

 /*code*/
  boost::function<int(int)> bar = _1 + 5;
  return bar(foo_var);


int main() 
return foo(1);

【讨论】:

@TheMask _1 是一种特殊类型,它具有所有基本运算符的重载以生成表达式树而不是执行任何操作。当使用operator() 向树传递参数时,它可以遍历构建的表达式树并用参数替换_N。要了解更多信息,您需要加强 MPL 和 Boost.Proto。【参考方案7】:

在 C++ 中,您可以通过其他可能的方式达到相同的效果。没有直接的嵌套函数实现。两个有用的链接:

http://www.respower.com/~earlye/programming/19990916.001.htm

http://www.devx.com/tips/Tip/40841

【讨论】:

【参考方案8】:

AFAIK,C++ 中不允许嵌套函数。

【讨论】:

以上是关于在 C++ 中模拟嵌套函数的主要内容,如果未能解决你的问题,请参考以下文章

在 C++ 中,是不是可以从将结束父函数的嵌套函数中返回?

如何在 C++ 的外部类构造函数中初始化嵌套类成员

函数不能嵌套,那么如何在 C++ 中做到这一点? [关闭]

从外部类 C++ 正确调用嵌套类中的函数

Oracle SQL 模拟嵌套窗口函数

C++ - 嵌套包含 - 避免“包含嵌套太深的错误”