为什么我不能转发声明类型定义?

Why can't I forward declare typedefs?

本文关键字:类型 定义 声明 转发 不能 为什么      更新时间:2023-10-16
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)的原因是什么?

你很困惑,或者你的例子没有显示你在问什么。在你的示例代码中,你不是试图"向前声明一个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 确实允许以下内容,因为结构名称和 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的用途,所以它的声明必须说明它是什么,而不仅仅是向前声明为一个名称。

让我解决第一个错误:

    创建类 A
  1. :此时,名称"A"被分配给该类;此作用域中没有其他实体可以称为"A"。
  2. 然后你键入 def,以便 K 现在引用 A,因此此作用域中的其他实体都不能称为"K"。
  3. 然后你尝试转发声明 K.转发声明本身很好,但名称 K 已经被你的 typedef 采用。在这一点上,它与A关系不大。您也无法转发声明 A,这两个名称都已被您以前的使用所采用。

你到底想做什么?

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

原则上允许在两个用例中使用"前向声明类"

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

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

另见:(Samuel P. Harbison, Guy L.Steele] C A Reference,第151页。