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

时间:2013-01-21 17:42:19

标签: 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...)
}

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

3 个答案:

答案 0 :(得分:14)

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

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

通过这些例子:

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

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

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

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

[旁白:C 允许以下内容,因为struct name和typedef名称位于不同的名称空间中:

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

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

但是根据你的评论,也许这不是你实际上想要做的事情。

根据您的评论,您可能会破坏您的例子,并且您真正想要做的是:

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

这声明了一个typedef,用于尚未定义的类型。

转发声明一个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

我认为你说你希望它有效,所以你希望这有效吗?

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

这应该有用,对吗?您不需要知道K的类型,因为您只传递指向它的指针,对吧?错误。如果您稍后定义K,请执行以下操作:

typedef int& K;

现在f的签名int&* f()无效。你必须知道typedef是的typedef ,所以它的声明必须说明是什么而不仅仅是将它声明为名称。

答案 1 :(得分:4)

让我解决第一个错误:

  1. 您创建了A类:此时,名称“A”被分配给该类;此范围内的其他实体不能称为“A”。
  2. 然后你输入dede以便K现在引用A,所以这个范围内的其他实体都不能被称为'K'。
  3. 然后你尝试转发声明K.前转声明本身很好,但你的typedef已经取名字K.在这一点上它与A几乎没有关系。您也无法转发声明A,这两个名称已经被您以前的用途所采用。
  4. 你还想做什么?

答案 2 :(得分:0)

我无法在C ++ 2003标准中找到这个东西。但是C编译器不允许这样的事情,因为typedef构造定义了新类型,然后你尝试通过 class A 再次定义新类型。

原则上,两个用例允许使用“前向声明类”

  1. 的typedef-名称
  2. 指向结构的指针
  3. 这两个操作都不需要有关sizeof类型和内存布局的信息。 同样在上面的列表中没有“引用”,因为C语言中没有引用。

    参见:(Samuel P. Harbison,Guy L.Steele)C A参考,第151页。