我的意思是:
int main()
{
void a()
{
// code
}
a();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
Kon*_*lph 254
对于所有意图和目的,C++通过lambdas支持:1
int main() {
auto f = []() { return 42; };
std::cout << "f() = " << f() << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
这里f是一个lambda对象,它充当了一个本地函数main.可以指定Captures以允许函数访问本地对象.
在幕后,f是一个功能对象(即提供的类型的对象operator()).函数对象类型由编译器基于lambda创建.
1,自C++ 11以来
sbi*_*sbi 218
不,C++不支持这一点.
编辑:这个答案很老.同时,C++ 11有lambda可以达到类似的结果 - 见下面的答案.
也就是说,你可以拥有本地类,并且它们可以具有函数(非static或者static),所以你可以在某种程度上得到它,尽管它有点像kludge:
int main() {
// This declares a lambda, which can be called just like a function
auto print_message = [](std::string message)
{
std::cout << message << "\n";
};
// Prints "Hello!" 10 times
for(int i = 0; i < 10; i++) {
print_message("Hello!");
}
}
Run Code Online (Sandbox Code Playgroud)
但是,我会质疑实践.每个人都知道(好吧,无论如何你现在都这样做:))C++不支持本地函数,所以他们习惯没有它们.但是,它们并没有被用于那个kludge.我会在这段代码上花一点时间来确保它只是允许本地函数.不好.
Seb*_*ach 41
已经提到了本地类,但是这里有一种方法可以让它们更像本地函数,使用operator()重载和匿名类:
int main() {
struct {
unsigned int operator() (unsigned int val) const {
return val<=1 ? 1 : val*(*this)(val-1);
}
} fac;
std::cout << fac(5) << '\n';
}
Run Code Online (Sandbox Code Playgroud)
我不建议使用它,这只是一个有趣的技巧(可以做,但imho不应该).
随着C++ 11的兴起,您现在可以拥有本地函数,其语法有点像JavaScript的回忆:
auto fac = [] (unsigned int val) {
return val*42;
};
Run Code Online (Sandbox Code Playgroud)
Nim*_*Nim 17
没有.
你想做什么?
解决方法:
int main(void)
{
struct foo
{
void operator()() { int a = 1; }
};
foo b;
b(); // call the operator()
}
Run Code Online (Sandbox Code Playgroud)
Leo*_*son 14
旧答案:你可以,但是你必须作弊并使用虚拟课:
void moo()
{
class dummy
{
public:
static void a() { printf("I'm in a!\n"); }
};
dummy::a();
dummy::a();
}
Run Code Online (Sandbox Code Playgroud)
更新的答案:较新版本的C++也支持lambdas更好/正确地做到这一点.查看页面上方的答案.
正如其他人所提到的,您可以通过在gcc中使用gnu语言扩展来使用嵌套函数.如果您(或您的项目)坚持使用gcc工具链,您的代码将基本上可以在gcc编译器所针对的不同体系结构中移植.
但是,如果可能需要使用不同的工具链编译代码,那么我将远离这些扩展.
使用嵌套函数时,我也会小心翼翼.它们是一个很好的解决方案,用于管理复杂但有凝聚力的代码块(其中的部分不适用于外部/一般用途).它们在控制命名空间污染方面也非常有用(对于自然复杂的/非常真实的关注/冗长的语言.)
但就像任何事情一样,他们可能会被滥用.
令人遗憾的是,C/C++不支持标准等功能.大多数pascal变体和Ada do(几乎所有基于Algol的语言都有).与JavaScript相同.与Scala等现代语言相同.与Erlang,Lisp或Python等古老语言相同.
就像使用C/C++一样,不幸的是,Java(我的大部分时间都是我的生活)并没有.
我在这里提到Java,因为我看到几个海报建议使用类和类'方法作为嵌套函数的替代.这也是Java中的典型解决方法.
简答:不.
这样做往往会在类层次结构中引入人为的,不必要的复杂性.在所有条件相同的情况下,理想的是使类层次结构(及其包含的名称空间和范围)尽可能简单地表示实际域.
嵌套函数有助于处理"私有",函数内复杂性.缺乏这些设施,人们应该尽量避免将"私人"复杂性传播到一个人的阶级模型中.
在软件(以及任何工程学科)中,建模是一个权衡问题.因此,在现实生活中,这些规则(或指导方针)将有合理的例外.但是要小心.
您不能在C++中使用本地函数.但是,C++ 11有lambdas.Lambdas基本上是像函数一样工作的变量.
一个lambda有这种类型std::function(实际上这不是真的,但在大多数情况下,你可以认为它是).要使用此类型,您需要#include <functional>.std::function是一个模板,使用语法作为返回类型和参数类型的模板参数std::function<ReturnType(ArgumentTypes).例如,std::function<int(std::string, float)>是一个lambda返回并带有int两个参数,一个std::string和一个float.最常见的是std::function<void()>,它不返回任何内容并且不带参数.
一旦声明了lambda,就会使用语法将其调用为普通函数lambda(arguments).
要定义lambda,请使用语法[captures](arguments){code}(还有其他方法,但我不会在这里提到它们).argumentslambda是什么参数,code是调用lambda时应该运行的代码.通常你放[=]或[&]作为捕获.[=]表示您捕获范围中的所有变量,其中值由value定义,这意味着它们将保留声明lambda时的值.[&]表示您通过引用捕获作用域中的所有变量,这意味着它们将始终具有其当前值,但如果它们从内存中擦除,则程序将崩溃.这里有些例子:
#include <functional>
#include <iostream>
int main(){
int x = 1;
std::function<void()> lambda1 = [=](){
std::cout << x << std::endl;
};
std::function<void()> lambda2 = [&](){
std::cout << x << std::endl;
};
x = 2;
lambda1(); //Prints 1 since that was the value of x when it was captured and x was captured by value with [=]
lambda2(); //Prints 2 since that's the current value of x and x was captured by value with [&]
std::function<void()> lambda3 = [](){}, lambda4 = [](){}; //I prefer to initialize these since calling an uninitialized lambda is undefined behavior.
//[](){} is the empty lambda.
{
int y = 3; //y will be deleted from the memory at the end of this scope
lambda3 = [=](){
std::cout << y << endl;
};
lambda4 = [&](){
std::cout << y << endl;
};
}
lambda3(); //Prints 3, since that's the value y had when it was captured
lambda4(); //Causes the program to crash, since y was captured by reference and y doesn't exist anymore.
//This is a bit like if you had a pointer to y which now points nowhere because y has been deleted from the memory.
//This is why you should be careful when capturing by reference.
return 0;
}
Run Code Online (Sandbox Code Playgroud)
您还可以通过指定名称来捕获特定变量.只需指定其名称将按值捕获它们,使用&before 指定其名称将通过引用捕获它们.例如,[=, &foo]将按值捕获所有变量,除非foo将通过引用[&, foo]捕获,并将通过引用捕获所有变量,除非foo将通过值捕获.您还可以仅捕获特定变量,例如[&foo]将foo通过引用捕获并且不捕获任何其他变量.您也可以通过使用来捕获任何变量[].如果您尝试在未捕获的lambda中使用变量,则无法编译.这是一个例子:
#include <functional>
int main(){
int x = 4, y = 5;
std::function<void(int)> myLambda = [y](int z){
int xSquare = x * x; //Compiler error because x wasn't captured
int ySquare = y * y; //OK because y was captured
int zSquare = z * z; //OK because z is an argument of the lambda
};
return 0;
}
Run Code Online (Sandbox Code Playgroud)
您无法更改由lambda中的值捕获的变量的值(由value捕获的变量const在lambda中具有类型).为此,您需要通过引用捕获变量.这是一个例子:
#include <functional>
int main(){
int x = 3, y = 5;
std::function<void()> myLambda = [x, &y](){
x = 2; //Compiler error because x is captured by value and so it's of type const int inside the lambda
y = 2; //OK because y is captured by reference
};
x = 2; //This is of course OK because we're not inside the lambda
return 0;
}
Run Code Online (Sandbox Code Playgroud)
此外,调用未初始化的lambda是未定义的行为,通常会导致程序崩溃.例如,永远不要这样做:
std::function<void()> lambda;
lambda(); //Undefined behavior because lambda is uninitialized
Run Code Online (Sandbox Code Playgroud)
例子
以下是使用lambdas在您的问题中想要做的代码:
#include <functional> //Don't forget this, otherwise you won't be able to use the std::function type
int main(){
std::function<void()> a = [](){
// code
}
a();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
这是一个更高级的lambda示例:
#include <functional> //For std::function
#include <iostream> //For std::cout
int main(){
int x = 4;
std::function<float(int)> divideByX = [x](int y){
return (float)y / (float)x; //x is a captured variable, y is an argument
}
std::cout << divideByX(3) << std::endl; //Prints 0.75
return 0;
}
Run Code Online (Sandbox Code Playgroud)
不,这是不允许的.无论ç也不是C++支持默认情况下此功能,但是TonyK指出(在评论),有扩展的GNU C编译器,使在C.这种行为
小智 7
所有这些技巧只是看(或多或少)作为本地函数,但它们不会那样工作.在本地函数中,您可以使用其超函数的局部变量.这是半全局的.没有这些技巧可以做到这一点.最接近的是来自c ++ 0x的lambda技巧,但是它的闭包是在定义时间中绑定的,而不是使用时间.
让我在这里发布一个我认为最干净的 C++03 解决方案。*
#define DECLARE_LAMBDA(NAME, RETURN_TYPE, FUNCTION) \
struct { RETURN_TYPE operator () FUNCTION } NAME;
...
int main(){
DECLARE_LAMBDA(demoLambda, void, (){ cout<<"I'm a lambda!"<<endl; });
demoLambda();
DECLARE_LAMBDA(plus, int, (int i, int j){
return i+j;
});
cout << "plus(1,2)=" << plus(1,2) << endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
(*) 在 C++ 世界中使用宏从来不被认为是干净的。
| 归档时间: |
|
| 查看次数: |
174631 次 |
| 最近记录: |