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

Kla*_*aim 7 c++ c++11

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...)
}
Run Code Online (Sandbox Code Playgroud)

标准C++不允许这些情况(1和2)编译的原因是什么?

Jon*_*ely 14

你很困惑,或者你的例子没有显示你所询问的内容.在您的示例代码中,您不是试图"转发声明一个typedef"(例如,事情是不可能的或有用的,见下文),您试图将现有的typedef-name(即一种类型的别名)重新声明为完全不同的类型.

你已经说过K是一个typedef A,然后你说它是一个类K.做好决定.它不能同时class Aclass K.(1)和(2)都因同样的原因而失败.

通过这些例子:

class A;   // ok
typedef A K; // ok
Run Code Online (Sandbox Code Playgroud)

到目前为止.

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

我不知道你为什么在这里说"C++ 11",这在C++ 03中也可以.类和结构在C++中是相同的东西.它们都是"对象类型"和"类类型".对于前向声明,类密钥(即structclass)是可互换的.

class K;   // (1) error: K is a typedef (of a class...)
Run Code Online (Sandbox Code Playgroud)

K已被声明为类的typedef A,该名称不能重用于在同一范围内声明新类型.

(旁白):C 确实允许以下,因为结构的名称和typedef名称是不同的命名空间:

struct A { };
typedef struct A K;  // N.B. need "struct A" not just "A"
struct K { }; 
Run Code Online (Sandbox Code Playgroud)

但现在有两种不同的类型被称为struct KK无关.这样做会让人感到困惑和愚蠢.]

但是根据你的评论,也许这不是你真正试图做的事情.

根据您的评论,您的破解示例可能具有误导性,您真正想要做的是:

typedef class A K;   // forward declare A as class and declare K as typedef for it
Run Code Online (Sandbox Code Playgroud)

这为尚未定义的类型声明了typedef.

这将是无用的前瞻性声明的typedef,你不能用它做任何事,因为你不知道它是什么样类型的类型定义,且有非常少的,你可以在C++做不知道有关的东西类型.在不知道它是否是对象类型,引用类型或函数类型的情况下,您可以实际为其声明另一个typedef!

考虑:

typedef K;   // declares K to be a typedef

K* f();      // function returning pointer to K
void g(K*);  // function taking pointer to K
Run Code Online (Sandbox Code Playgroud)

我想你说你希望它有效,所以你期望这个有效吗?

K* k = f();
g(k);
Run Code Online (Sandbox Code Playgroud)

那应该有用,对吗?你不需要知道它的类型,K因为你只传递指针,对吧?错误.如果您稍后定义K如下:

typedef int& K;
Run Code Online (Sandbox Code Playgroud)

现在f签名int&* f()无效.你必须知道的类型定义是什么类型定义,所以它的声明必须说什么不是只是把它前瞻性声明的名称.

  • "向前声明一个typedef是没用的,你不能对它做任何事情,因为你不知道它是什么类型的typedef,并且在C++中你几乎无法知道一些事情.一种." - 那么为什么没有"很少你可以做"的前进声明类.如果你可以转发声明一个类,为什么你不能转发声明一个typedef?在这两种情况下,原因是当在另一个头中提到名称(作为函数参数)时,避免包括类型的头.您只想告诉编译器,此类型(def)存在. (5认同)
  • “重新申报”是我们试图避免的问题。它不是“typedef A B”,而是“typedef(大毛茸茸的混乱)B”,而且您不想重复那个大毛茸茸的混乱。 (2认同)