[英]Why is this a forward declaration in C++?
I will have the following code snippet in utilA.cpp: 我将在utilA.cpp中有以下代码片段:
// utilB.h
namespace xm
{
void zoo(struct tm timeval); //<-----line 0
}
// utilA.cpp
#include <utilB.h> //<----line 1
#include <time.h> //<----line 2
namespace xm
{
void foo()
{
struct tm time1 = {0}; //<----line 3
}
}
GCC complains when compiling utilA.cpp, GCC在编译utilA.cpp时抱怨,
error: variable 'xm::tm time1' has initializer but incomplete type
It seems this is because the utilA.h
is using struct tm
in line 0, but without include the time.h
, and the compiler treat the struct tm
in line 0 as a forward declare, so the struct tm
at line 2 is resolved as xm::tm
inside the header at line 0. 这似乎是因为
utilA.h
在第0行使用struct tm
,但没有包含time.h
,编译器将第0行中的struct tm
视为前向声明,因此第2行的struct tm
被解析为第0行标题内的xm::tm
。
So does the C++ standard define this struct tm
as an type of function parameter as forward declaration? 那么C ++标准是否将此
struct tm
定义为一种函数参数作为前向声明? Please help to explain this and quotes from the standard will helpful. 请帮助解释一下,标准中的引用会有所帮助。
In line 0, you declared a class named tm
inside the xm
namespace. 在第0行中,您在
xm
命名空间内声明了一个名为tm
的类。 Yes, C++ allows declaring types in function/template parameters. 是的,C ++允许在函数/模板参数中声明类型。
N4140 § 3.4.4 [basic.lookup.elab]/2
N4140§3.4.4[basic.lookup.elab] / 2
If the elaborated-type-specifier is introduced by the class-key and this lookup does not find a previously declared type-name , or if the elaborated-type-specifier appears in a declaration with the form:
如果由类键引入了elaborated-type-specifier ,并且此查找未找到先前声明的类型名称 ,或者如果elaborated-type-specifier出现在具有以下形式的声明中:
class-key attribute-specifier-seq opt identifier ;
class-key attribute-specifier-seq opt identifier ;
the elaborated-type-specifier is a declaration that introduces the class-name as described in 3.3.2.
elaborated-type-specifier是一个声明,它引入了3.3.2中描述的类名。
Because you declared a class named tm
inside the xm
namespace, it's the first name that name lookup finds for tm
in line 3. ::tm
(and ::std::tm
) are not considered. 因为你宣布一个名为类
tm
里面xm
命名空间,这是该名称查找发现的第一个名字tm
在第3行::tm
(和::std::tm
)不考虑。 And since there's no definition of class ::xm::tm
, the compiler complains about it being an incomplete type. 由于没有class
::xm::tm
定义,编译器抱怨它是一个不完整的类型。
If you weren't writing C code in C++, you'd write something like 1 如果你不是用C ++编写C代码,你会写一些类似1的东西
struct tm;
namespace xz{
void zoo(tm timeval);
}
or 要么
#include <ctime>
namespace xz{
void zoo(tm timeval);
}
and you wouldn't have that problem. 你不会有这个问题。
1 remember that you cannot forward-declare names in namespace std 1 记住你不能在名称空间std中转发声明名称
So does C++ standard define this
struct tm
as an type of function parameter as forward declaration.因此,C ++标准将此
struct tm
定义为一种函数参数作为前向声明。 Please help to explain this and quota from the standard will helpful.请帮助解释这个和标准配额会有所帮助。
Yes, struct tm timeval
will introduce a new class name xm::tm
here. 是的,
struct tm timeval
将在这里引入一个新的类名xm::tm
。
(explanations and quotes) (解释和引用)
struct tm
is a elaborated type specifier , which could be used to introduce a new class name. struct tm
是一个精心设计的类型说明符 ,可用于引入新的类名。
$3.1/4 Declarations and definitions [basic.def] $ 3.1 / 4声明和定义[basic.def]
[ Note: A class name can also be implicitly declared by an elaborated-type-specifier ([dcl.type.elab]).
[注意:类名也可以由elaborated-type-specifier([dcl.type.elab])隐式声明。 — end note ]
- 结束说明]
$9.1/2 Class names [class.name] : $ 9.1 / 2班级名称[class.name] :
A declaration consisting solely of class-key identifier;
仅由类密钥标识符组成的声明; is either a redeclaration of the name in the current scope or a forward declaration of the identifier as a class name.
是对当前作用域中名称的重新声明,或者是作为类名称的标识符的前向声明。 It introduces the class name into the current scope.
它将类名引入当前范围。
$3.4.4/2 Elaborated type specifiers [basic.lookup.elab] : $ 3.4.4 / 2详细说明的类型说明符[basic.lookup.elab] :
or if the elaborated-type-specifier appears in a declaration with the form:
或者如果详细说明类型说明符出现在声明中,其形式如下:
class-key attribute-specifier-seqopt identifier ;
the elaborated-type-specifier is a declaration that introduces the class-name as described in [basic.scope.pdecl].
elaborated-type-specifier是一个声明,它引入了[basic.scope.pdecl]中描述的类名。
$3.3.2/7 Point of declaration [basic.scope.pdecl] : $ 3.3.2 / 7声明点[basic.scope.pdecl] :
if the elaborated-type-specifier is used in the decl-specifier-seq or parameter-declaration-clause of a function defined in namespace scope, the identifier is declared as a class-name in the namespace that contains the declaration;
如果在命名空间作用域中定义的函数的decl-specifier-seq或parameter-declaration-clause中使用了elaborated-type-specifier,则在包含声明的命名空间中将标识符声明为类名。
For struct tm timeval
used as function parameter declaration, because <time.h>
is not included and there's still no class named tm
, class tm
will be declared in current scope (ie namespace xm
), then xm::tm
will be forward declared. 对于用作函数参数声明的
struct tm timeval
,因为没有包含<time.h>
并且仍然没有名为tm
类,所以将在当前作用域(即名称空间xm
)中声明类tm
,然后将xm::tm
声明为前向声明。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.