Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/148.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ C++;在类中向前声明类_C++ - Fatal编程技术网

C++ C++;在类中向前声明类

C++ C++;在类中向前声明类,c++,C++,下面是一段简单的代码,尽管我不明白为什么: class C { class B; class A { B getB() { return B(); } }; class B { }; }; int main(int, char**) { return 0; } 如果我随后注释掉“class C”内容,使得B的前向声明、A的定义和B的定义不再嵌套在类中,则代码不会编译,因为B的类型不完整: main.cpp: In membe

下面是一段简单的代码,尽管我不明白为什么:

class C {
    class B;

    class A {
        B getB() { return B(); }
    };

    class B {
    };
};

int main(int, char**)
{
    return 0;
}
如果我随后注释掉“
class C
”内容,使得
B
的前向声明、
A
的定义和
B
的定义不再嵌套在类中,则代码不会编译,因为
B
的类型不完整:

main.cpp: In member function 'B A::getB()':
main.cpp:6: error: return type 'struct B' is incomplete
main.cpp:6: error: invalid use of incomplete type 'struct B'
main.cpp:3: error: forward declaration of 'struct B'

我理解类型不完整意味着什么,也就是说它还没有定义,因此编译器不可能知道要为它分配多少空间。但是为什么在上面的代码中
B
不被认为是不完整的,其中
A
B
都是在
C
中声明和定义的呢?

标准明确规定,方法的主体在包含它的类之后进行解释


因此,在计算
C::A::getB()
的主体时,
A
B
C
都是完整的类型。

内联成员函数的主体在类定义被完全处理之前不会被处理

因此,您可以使用:

class A 
{
   class B;
   B getB() { return B(); }

   class B {};
};
这还允许在内联成员函数定义中使用尚未声明的成员变量

class Foo
{
   int getBar() { return bar; }

   int bar;
};
我猜同样的逻辑也被扩展到嵌套类的成员函数的内联定义中——也就是说,在包含类的定义被完全处理之前,它们不会被处理

PS我无法在标准中快速找到可验证我的声明的参考


PS 2在标准中引用了使问题中的代码有效的代码。

我认为这是由于:

类中声明的名称的潜在作用域不仅包括 名称的声明点,以及该类中所有函数体、默认参数、异常规范和非静态数据成员的大括号或相等初始值设定项(包括嵌套 课程)

也就是说,
B
的完整声明的范围包括嵌套类的成员函数体:

class C {
    class B; // (1)

    class A { 
        B getB() {
            return B(); // both (1) and (2) in scope here
                        // since (2) is the complete type declaration,
                        // this is perfectly fine
        }
    };

    class B { // (2)
    };
};

相比之下,如果
C
是名称空间而不是类,则类
B
的完整声明的范围不会扩展到
a::getB()
。唯一可见的声明将是我标记为
(1)
B
的前向声明,因此
B()
将是不完整类型的构造

此外,当我需要向前声明嵌套类时,我往往会在代码中嗅到一些糟糕的设计,我使用的技巧是:

// Foo.h
class Foo {
    class Bar {
    };
};
class Foobar : public Foo::Bar {};


// Zoo.h
/* Fwd declare */
class FooBar;

有没有可能你知道我在哪里能找到那些废话?试着找到它。。。不幸的是,“成员职能”一词在2015年标准PDF草案中被提及582次。。。你抢先找到了答案。我试图找到标准。我认为,在名称查找过程中,类似地,当类X的成员函数定义中使用的非限定id(5.1)解析为静态成员、枚举器或类X的嵌套类型或基类X时,非限定id将转换为限定id(5.1)其中嵌套的名称说明符命名成员函数的类。来自[class.mfct.non static]。如果你同意的话,就用吧。@NathanOliver,我认为那不对。这只是说将找到
B
,但是由于转发声明,无论怎样都会找到
B
。我不知道正确的部分在哪里,也找不到。也许如果类X是在命名空间范围中定义的,那么嵌套的类Y可以在类X中声明,然后在类X的定义中定义,或者稍后在包含类X定义的命名空间范围中定义。from[class.nest]@NathanOliver该部分(尽管这个例子非常接近)基本上只允许你向前声明嵌套类。我还在寻找。太棒了,谢谢你澄清了这一点。提出这个特殊问题的是libpqxx的类,它有嵌套的
tuple
field
类,其中
tuple
在它的一个函数体中构造一个
field
(即第183行)