C++中是否有像Java一样的静态嵌套类?

12

我经常使用Java编写代码,但是在C ++中的静态嵌套类方面有点困惑。

我试图声明一个静态类,但是遇到了错误:

class D
{
    public:

    static class Listener
    {
        public :

        void foo()
        {
            cout << "foo" <<endl;
        }
    };

};

我遇到了以下错误:

"storage class can only be specified for objects and functions"

(我正在使用在线编译器)。


只需跳过“static”即可,这样就可以了。在C++中,在此上下文中不需要它。 - Frank Puffer
3
C++内部类中没有包含外部类的上下文信息。它们默认类似于Java中的"静态"类。 - StoryTeller - Unslander Monica
3
“静态内部类”在Java中是一个自相矛盾的概念:“内部类是指未显式或隐式声明为静态的嵌套类。” - user207421
2个回答

27

正确的术语应该是“静态嵌套类”。

Java中的静态嵌套类与C++中的普通嵌套类类似,只需去掉static即可正常工作。

像Java中的非静态嵌套类在C++中会更难模拟,因为没有编译器魔法来自动提供外部类的上下文。您需要通过在内部类中存储对外部类的引用,在内部类的构造函数中初始化它,并通过引用显式访问外部类的成员来解决此问题。


3
在Java中,不存在所谓的"static inner class"。 - user207421
@EJP:我猜“静态嵌套类”和“非静态嵌套类”应该是正确的术语? - Christian Hackl
@EJP:好了,我修好了 :) - Christian Hackl
1
要完全清楚:在C++中,正确的术语是“嵌套类”。在C++中,没有所谓的“静态类”,无论是嵌套还是其他。 - Pete Becker

3

C++中的类仅仅是嵌套类型定义,因此只作为嵌套类型定义的命名空间。

如果你在任何地方(无论是嵌套还是非嵌套)声明一个静态的类类型定义,你将会得到编译器警告并且它将被移除。类不能有存储类说明符,而static在类内部已经被重新用于其他目的。这是因为类类型根本没有存储,并且只是模板(因此链接没有意义;它们甚至没有生存到那一步),方法定义是编译器指令,当编译器选择时它能够具体化,但也可以轻松地从汇编输出中排除,与常规函数不同,当放置在另一个翻译单元中时,它们保证存在,因此所有类成员都有效地是 inline (除非是 static ,那么它们需要显式地成为内联定义)。 static 在类内部使用是多余的,因为嵌套类在这个意义上隐式地是 static

当你实例化父类时,它不包括嵌套类,因为这只是一个编译器指令。必须在其中一个成员中包含类的对象,其中类类型定义在范围内:

class c {
  public :
  int i;
  class s f; //not allowed
  class s;
  class s k; //not allowed, still has forward declaration type
  class s {
    public:
    int j;    
  };
  s p; // allowed
};

在类中可以前向声明嵌套类,但是除非它是指向该类型的指针或引用,在不完整的类型的前向声明中不能定义成员,但如果上层作用域中已经完成了该类型,则可以使用不完整类型。

然而,与命名空间不同,您无法从嵌套类访问父类的非静态成员(在命名空间中不存在这种静态和非静态)。这是因为嵌套类是单独实例化的,而父类可能永远不会实例化。程序员可以像在指针或本地指针中存储对象一样,将嵌套对象初始化在父对象中,但在对象级别上,它们是分开的对象,它们的类型定义所在的位置是无关紧要的。如果调用了父类的非静态成员,编译器将不得不传递父类对象的一个实例给它。理论上,它可以使用父类类型定义来确定它所填充的成员在内存中的偏移量,但它可能并不总是父对象的子对象。为了允许此功能,如果未实例化父类并将其分配为父子对象的子对象时,编译器将抛出错误以阻止子类的实例化。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接