8
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)编译的原因是什么?

4

3 回答 3

14

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

你已经说过K是 typedef for A,然后你说它是 class 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已被声明为 class 的 typedef A,该名称不能用于在同一范围内声明新类型。

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

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

但是现在有两种不同的类型叫做struct Kand K,它们是不相关的。这样做会令人困惑且非常愚蠢。]

但从你的评论来看,这可能不是你真正想要做的。

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

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 因此它的声明必须说明它不仅仅是向前声明它作为名称。

于 2013-01-22T15:18:09.580 回答
4

让我解决第一个错误:

  1. 您创建类 A:此时,将名称“A”分配给该类;此范围内的任何其他实体都不能称为“A”。
  2. 然后你 typedef 让 K 现在指代 A,所以在这个范围内没有其他实体可以称为“K”。
  3. 然后你尝试转发声明 K。转发声明本身很好,但名称 K 已经被你的 typedef 使用了。在这一点上,它与 A 几乎没有关系。您也无法转发声明 A,这两个名称都已被您以前的用途所采用。

你到底想做什么?

于 2013-01-21T18:16:35.187 回答
0

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

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

  1. 类型定义名称
  2. 指向结构的指针

这两个操作都不需要有关 sizeof 类型及其内存布局的信息。同样在上面的列表中没有“引用”,因为在 C 语言中没有引用。

另请参阅:(Samuel P. Harbison,Guy L.Steele] CA 参考资料,第 151 页。

于 2015-07-28T02:05:02.270 回答