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行)