简体   繁体   English

为什么我不能转发声明typedef?

[英]Why can't I forward declare typedefs?

namespace O
{
    class A{};


    class A;   // ok
    typedef A K; // ok

    struct A;  // ok(C++11): A is a class but for references and pointer it have the same meaning
    class K;   // (1) error: K is a typedef (of a class...)
}

namespace U
{
    typedef O::A A;


    class A;      // (2) error: A is a typedef (of  a class...)
}

What is the reason(s) standard C++ don't allow these cases (1 & 2) to compile? 标准C ++不允许这些情况(1和2)编译的原因是什么?

You are confused or your example doesn't show what you're asking about. 你很困惑,或者你的例子没有显示你所询问的内容。 In your example code you are not trying to "forward declare a typedef" (such as thing isn't possible or useful, see below) you are trying to redeclare an existing typedef-name (ie an alias for one type) as a completely different type. 在您的示例代码中,您不是试图“转发声明一个typedef”(例如,事情是不可能的或有用的,见下文),您试图将现有的typedef-name(即一种类型的别名)重新声明为完全不同的类型。

You've already said K is a typedef for A , then you say it's a class K . 你已经说KA的typedef,然后你说它是K级。 Make your mind up. 做好决定。 It's can't be both class A and class K . 它不能同时是class A class Kclass K Both (1) and (2) fail for that same reason. (1)和(2)都因同样的原因而失败。

Going through these lines of the example: 通过这些例子:

class A;   // ok
typedef A K; // ok

Right so far. 到目前为止。

struct A;  // ok(C++11): A is a class but for references and pointer it have the same meaning

I don't know why you've said "C++11" here, this is OK in C++03 too. 我不知道你为什么在这里说“C ++ 11”,这在C ++ 03中也可以。 Classes and structs are the same kind of thing in C++. 类和结构在C ++中是相同的东西。 They are both "object types" and both "class types". 它们都是“对象类型”和“类类型”。 For a forward declaration the class-key (ie struct or class ) is interchangeable. 对于前向声明,类键(即structclass )是可互换的。

class K;   // (1) error: K is a typedef (of a class...)

K has been declared as a typedef for class A , the name can't be reused for declaring a new type in the same scope. K已被声明为类A的typedef,该名称不能重用于在同一范围内声明新类型。

[Aside: C does allow the following, because struct names and typedef names are in separate namespaces: (旁白):C 确实允许以下,因为结构的名称和typedef名称是不同的命名空间:

struct A { };
typedef struct A K;  // N.B. need "struct A" not just "A"
struct K { }; 

But now there are two different types called struct K and K , which are unrelated. 但是现在有两种不同的类型叫做struct KK ,它们是无关的。 Doing this would be confusing and pretty dumb.] 这样做会让人感到困惑和愚蠢。]

But from your comments maybe that's not what you're actually trying to do anyway. 但是根据你的评论,也许这不是你真正试图做的事情。

Based on your comments maybe your broken examples are misleading and what you really want to do is: 根据您的评论,您的破解示例可能具有误导性,您真正想要做的是:

typedef class A K;   // forward declare A as class and declare K as typedef for it

This declares a typedef, for a type which is not defined yet. 对于尚未定义的类型,它声明了typedef。

It would be useless to forward-declare a typedef, you couldn't do anything with it because you wouldn't know what kind of type it was a typedef for , and there is very little you can do in C++ without knowing something about a type. 这将是无用的前瞻性声明的typedef,你不能用它做任何事,因为你不知道它是什么样的类型一个typedef,并有很少的,你可以在C ++做不知道有关的东西类型。 Without knowing if it's an object type, reference type or function type all you can realistically do is declare another typedef for it! 在不知道它是否是对象类型,引用类型或函数类型的情况下,您可以实际为其声明另一个typedef!

Consider: 考虑:

typedef K;   // declares K to be a typedef

K* f();      // function returning pointer to K
void g(K*);  // function taking pointer to K

I think you're saying you want that to be valid, so do you expect this to work? 我想你说你希望它有效,所以你期望这个有效吗?

K* k = f();
g(k);

That should work, right? 那应该有用,对吗? You don't need to know the type of K because you only pass around pointers to it, right? 你不需要知道K的类型,因为你只传递指向它的指针,对吧? Wrong. 错误。 What if you later define K like this: 如果您稍后将K定义为:

typedef int& K;

Now f has the signature int&* f() which is invalid. 现在f有签名int&* f()无效。 You have to know what a typedef is a typedef for , so its declaration has to say what it is not just forward-declare it as a name. 你必须知道一个typedef是什么的类型定义,所以它的声明有说这不是只是把它前瞻性声明的名称。

Let me just tackle the first error: 让我来解决第一个错误:

  1. You create class A: at this point, the name 'A' is assigned to that class; 您创建了A类:此时,名称“A”被分配给该类; no other entities in this scope can be called 'A'. 此范围内的其他实体不能称为“A”。
  2. Then you typedef so that K now refers to A, so no other entities in this scope can be called 'K'. 然后你输入def以便K现在引用A,所以这个范围内的其他实体都不能称为'K'。
  3. Then you try to forward declare K. Forward declaration on its own is fine, but the name K is already taken by your typedef. 然后你尝试转发声明K.前置声明本身很好,但你的typedef已经取名字K. It has little to do with A at this point. 在这一点上它与A几乎没有关系。 You wouldn't be able to forward declare A either, both names are already taken by your previous uses. 您也无法转发声明A,这两个名称已被您以前的使用所取代。

What are you trying to do anyways? 无论如何你还想做什么?

I can not found this thing in C++2003 standard. 我无法在C ++ 2003标准中找到这个东西。 But C compiler doesn't allow such thing because typedef construction define new type, and then you try to define new type one more time via class A . 但是C编译器不允许这样的事情,因为typedef构造定义了新类型,然后你尝试通过类A再次定义新类型。

In principle usage of "forward declaration class" was allowed for two use cases: 原则上,两个用例允许使用“前向声明类”

  1. typedef-names 的typedef名
  2. pointer to the structure 指向结构的指针

This both operations doesn't need info about sizeof type and it's memory layout. 这两个操作都不需要有关sizeof类型和内存布局的信息。 Also in list above there is no "references" because there is no reference s in C language. 同样在上面的列表中没有“引用”,因为C语言中没有引用。

See also: (Samuel P. Harbison, Guy L.Steele] CA Reference, page 151. 另见:(Samuel P. Harbison,Guy L.Steele)CA Reference,第151页。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM