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)编译的原因是什么?
答案 0 :(得分:14)
您感到困惑,或者您的示例没有显示您所询问的内容。在您的示例代码中,您不是试图“转发声明一个typedef”(例如,事情是不可能的或有用的,见下文),您试图将现有的typedef-name(即一种类型的别名)重新声明为完全不同的类型。
您已经说K
是A
的typedef,然后您说它是一个类K
。做好决定。它不能同时是class A
和class 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 ++中是相同的东西。它们都是“对象类型”和“类类型”。对于前向声明,类密钥(即struct
或class
)是可互换的。
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 K
和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 ,所以它的声明必须说明是什么而不仅仅是将它声明为名称。
答案 1 :(得分:4)
让我解决第一个错误:
你还想做什么?
答案 2 :(得分:0)
我无法在C ++ 2003标准中找到这个东西。但是C编译器不允许这样的事情,因为typedef构造定义了新类型,然后你尝试通过 class A 再次定义新类型。
原则上,两个用例允许使用“前向声明类”:
这两个操作都不需要有关sizeof类型和内存布局的信息。 同样在上面的列表中没有“引用”,因为C语言中没有引用。
参见:(Samuel P. Harbison,Guy L.Steele)C A参考,第151页。