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 (つまり、1 つの型のエイリアス) を完全に再宣言しようとしています。異なるタイプ。

Kは の typedefだと既に言いましたがA、それは class だと言います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は class の typedef として宣言されていますA。同じスコープで新しい型を宣言するために名前を再利用することはできません。

[余談:構造体名と typedef 名は別の名前空間にあるため、C では次のことが許可されます。

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

しかし、今では と という 2 つの異なるタイプがstruct KありK、これらは無関係です。これを行うと、混乱を招き、かなり馬鹿げたものになります。]

しかし、あなたのコメントから、それはあなたが実際にやろうとしていることではないかもしれません.

あなたのコメントに基づいて、壊れた例が誤解を招く可能性があり、本当にやりたいことは次のとおりです。

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

これは、まだ定義されていない型の typedef を宣言します。

typedef を前方宣言しても意味がありません。typedef の typedef がどのような型であるかがわからないため、何もできませ。タイプ。それがオブジェクト型なのか、参照型なのか関数型なのかわからなくても、現実的にできることは、別の 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. 次に、K が A を参照するように typedef するため、このスコープ内の他のエンティティを「K」と呼ぶことはできません。
  3. 次に、K を前方宣言しようとします。前方宣言自体は問題ありませんが、K という名前は既に typedef によって使用されています。この時点で、A とはほとんど関係がありません。A を前方宣言することもできません。両方の名前は、以前の使用で既に使用されています。

とにかく何をしようとしていますか?

于 2013-01-21T18:16:35.187 に答える