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

Rob*_*uld 81 c++ functional-programming data-structures

我只是在C++中错误地做了类似的事情,并且它有效.我为什么要这样做?

int main(int argc, char** argv) {
    struct MyStruct
    {
      int somevalue;
    };

    MyStruct s;
    s.somevalue = 5;
}
Run Code Online (Sandbox Code Playgroud)

在做完这个之后,我记得很久以前在某个地方读过这个技巧,作为一种穷人用于C++的函数式编程工具,但我不记得为什么这个有效,或者我读到它.

欢迎回答任何一个问题!

注意:虽然在写这个问题时我没有得到任何关于这个问题的引用,但是当前的侧边栏指出了它,所以我会把它放在这里供参考,无论哪种方式问题都不同但可能有用.

j_r*_*ker 68

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

定义本地类的能力让(类与创建自定义仿函数operator()()传递到,例如,比较功能std::sort()与使用或"循环体" std::for_each()),就方便多了.

不幸的是,C++禁止将本地定义的类与模板一起使用,因为它们没有链接.由于仿函数的大多数应用程序都涉及在仿函数类型上模板化的模板类型,因此本地定义的类不能用于此 - 您必须在函数外部定义它们.:(

[编辑1/11/2009]

该标准的相关引用是:

14.3.1/2:.本地类型,没有链接的类型,未命名的类型或从这些类型中的任何类型复合的类型不应该用作模板类型参数的模板参数.

  • 在C++ 11中取消了这一限制. (7认同)
  • 虽然凭经验,这似乎适用于MSVC++ 8.(但不是用g ++.) (2认同)

Nik*_*sov 28

本地定义的C++类的一个应用是工厂设计模式:


// 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;
}

Run Code Online (Sandbox Code Playgroud)

虽然您可以使用匿名命名空间执行相同操作.

  • 这是一个很好的想法,不确定我是否会很快使用它,但可能是一个很好的人在酒吧拉出来打动一些小鸡:) (23认同)
  • 大声笑罗伯特......是的,没有什么能让人知道如何了解C++的模糊角落...... (9认同)
  • (我说的是小鸡BTW,而不是答案!) (2认同)

Cha*_*tin 9

好吧,基本上,为什么不呢?structC中的A (回到时间的早晨)只是宣告记录结构的一种方式.如果你想要一个,为什么不能在声明一个简单变量的地方声明呢?

一旦你这样做,那么请记住,如果可能的话,C++的目标是与C兼容.所以它留了下来.


小智 7

这对于进行一些基于堆栈的异常安全工作实际上非常有用.或者从具有多个返回点的函数进行一般清理.这通常被称为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.
}
Run Code Online (Sandbox Code Playgroud)

  • `Cleaner cleaner();`我认为这将是函数声明而不是对象定义. (5认同)
  • 即使在函数内部,像这样的类也*准确地*是 C++ 中的 RAII 的全部内容。 (3认同)
  • @用户您是正确的。要调用默认构造函数,他应该编写“ Cleaner cleaner;”或“ Cleaner cleaner {};”。 (2认同)

Chr*_*isW 5

例如,在http://www.icce.rug.nl/documents/cplusplus/cplusplus07.html的 "7.8:本地类:函数内部"一节中提到它,它称之为"本地类",并称之为"在涉及继承或模板的高级应用程序中非常有用".