为什么我可以用C ++定义函数中的结构和类?

我只是在C ++中错误地做了这样的事情,而且工作。 我为什么要这样做?

int main(int argc, char** argv) { struct MyStruct { int somevalue; }; MyStruct s; s.somevalue = 5; } 

在做完这些之后,我很早以前就想起了一个关于这个诀窍的方法,作为一种穷人的C ++函数式编程工具,但是我不记得为什么这个方法是有效的,或者是我读过的。

任何问题的答案都欢迎!

注意:虽然在写这个问题时我没有得到任何关于这个问题的参考,但现在的边栏指出了,所以我把它放在这里作为参考,不pipe怎样,问题是不同的,但可能是有用的。

[编辑18/4/2013]:令人高兴的是,下面提到的限制已经被C ++ 11取消了,所以本地定义的类毕竟是有用的! 感谢评论者bamboon。

在本地定义类的能力将使创build自定义函子(具有operator()() ,例如比较函数传递给std::sort()或“循环体”与std::for_each()更方便。

不幸的是,C ++禁止在模板中使用本地定义的类 ,因为它们没有链接。 由于大多数仿函数的应用程序都涉及在仿函数types上模板化的模板types,因此本地定义的类不能用于此 – 您必须在函数之外定义它们。 🙁

[编辑1/11/2009]

标准中的相关引用是:

14.3.1 / 2:一个本地types,一个没有链接的types,一个未命名的types或者从这些types中复合的types都不能作为模板types参数的模板参数。

本地定义的C ++类的一个应用程序是工厂devise模式 :

 // In some header class Base { public: virtual ~Base() {} virtual void DoStuff() = 0; }; Base* CreateBase( const Param& ); // in some .cpp file Base* CreateBase( const Params& p ) { struct Impl: Base { virtual void DoStuff() { ... } }; ... return new Impl; } 

虽然你可以用匿名命名空间做同样的事情。

那么,基本上,为什么不呢? C中的struct (回到时间的黎明)只是一种声明logging结构的方法。 如果你想要一个,为什么不能声明它将声明一个简单的variables?

一旦你这样做,那么记住C ++的一个目标就是尽可能与C兼容。 所以它保持。

这对于做一些基于堆栈的exception安全工作非常有用。 或者从具有多个返回点的函数中进行一般的清理。 这通常被称为RAII(资源获取初始化)习语。

 void function() { struct Cleaner { Cleaner() { // do some initialization code in here // maybe start some transaction, or acquire a mutex or something } ~Cleaner() { // do the associated cleanup // (commit your transaction, release your mutex, etc.) } }; Cleaner cleaner(); // Now do something really dangerous // But you know that even in the case of an uncaught exception, // ~Cleaner will be called. // Or alternatively, write some ill-advised code with multiple return points here. // No matter where you return from the function ~Cleaner will be called. } 

例如,在http://www.icce.rug.nl/documents/cplusplus/cplusplus07.html中的; “7.8:本地类:函数内的类”一节中提到,它将其称为“本地类”,并称其为“在涉及inheritance或模板的高级应用程序中非常有用“。

这是为了使正确初始化的对象数组。

我有一个C类没有默认的构造函数。 我想要一个C类对象的数组。我弄清楚我想如何初始化这些对象,然后用一个静态方法从C中派生一个D类,该方法为D的默认构造函数中的C提供参数:

 #include <iostream> using namespace std; class C { public: C(int x) : mData(x) {} int method() { return mData; } // ... private: int mData; }; void f() { // Here I am in f. I need an array of 50 C objects starting with C(22) class D : public C { public: D() : C(D::clicker()) {} private: // I want my C objects to be initialized with consecutive // integers, starting at 22. static int clicker() { static int current = 22; return current++; } }; D array[50] ; // Now I will display the object in position 11 to verify it got initialized // with the right value. cout << "This should be 33: --> " << array[11].method() << endl; cout << "sizodf(C): " << sizeof(C) << endl; cout << "sizeof(D): " << sizeof(D) << endl; return; } int main(int, char **) { f(); return 0; } 

为了简单起见,这个例子使用一个简单的非默认构造函数和一个在编译时已知值的情况。 将这种技术扩展到需要用仅在运行时已知的值初始化的对象数组的情况很简单。