3

enum MyEnum : intC++が共変であると認識しないのはなぜintですか?

例: http://ideone.com/Ns1O2d

#include <iostream>

enum FooType : int
{
    Crazy = 0,
    Cool
};

enum BarType : int
{
        Hello = Cool + 1,
        World
};

class Foo
{
public:
        Foo(void)
        {
        }

        ~Foo(void)
        {
        }

        virtual int getType(void) 
        {
                        return Crazy;
        }
};

class Bar : public Foo
{
public:
        Bar(void)
        {
        }

        ~Bar(void)
        {
        }

        virtual BarType getType(void)
        {
                return Hello;
        }
};

int main(int argc, char* argv[])
{
        Bar f = Bar();           
        std::cout << f.getType() << std::endl;
        return 0;
}

コンパイル エラー:

prog.cpp:43:18: error: conflicting return type specified for 'virtual BarType Bar::getType()'
prog.cpp:26:14: error:   overriding 'virtual int Foo::getType()'
4

4 に答える 4

3

スコープのない列挙型 (つまり、andではenumsなく通常の) は、整数への暗黙的な昇格を提供します。つまり、これを行うことができます。enum classenum struct

enum FooType : int { Crazy, Cool };
int val = Crazy; // promotion to integer

ただし、これは逆には機能しません。

FooType val = 0;  // illegal

これは §7.2/5 に従います:各列挙は、 §7.2/9 と組み合わせて、他のすべての型とは異なる型を定義します:列挙子の値または範囲指定されていない列挙型のオブジェクトは、整数昇格によって整数に変換されます.

このルールの理由は非常に明白だと思います。対応する列挙子が定義されていない整数値が存在する可能性があります (そして、一般的に存在します)。上記の例では、0とを変換1することは理論的に可能ですが、2またはそれ以上の数を変換することはできませんでした。

ただし、列挙がその基になる型(例では)に対して共変intである場合、定義した意味で、次のことが可能になります。

class Foo
{
public:
  virtual ~Foo(void) {}
  virtual int getType(void) 
  {
    return Crazy;
  }
};

class Bar : public Foo
{
public:
  virtual ~Bar(void) {}
  virtual BarType getType(void)
  {
    return Foo::getType();
  }
};

派生クラスでBar::getType()は、 が を返すように定義されていますが、これはBarType継承された関数 を呼び出すことによって行われFoo::getType()ます。これは完全に正当です。

書かれているようにこれが可能である場合、結果の を からBar::getType()に暗黙的に変換する必要があります。上で説明したように、これはあり得ません。intFoo::getType()int


Bar::getTypeただし、と同じ方法で宣言することにより、コードが意図しているように見えるものを実現し、 a (暗黙的に に昇格されます)をFoo:getType返すことができます。BarTypeint

class Bar : public Foo
{
public:
  virtual ~Bar(void) {}
  virtual int getType(void)
  {
    return Hello;
  }
};

これは、基になる型がint(列挙型の宣言で修正したためint) であり、列挙型がスコープされていない (つまり、enum classorを使用していないenum struct) 場合にのみ機能することに注意してください。

于 2012-11-08T02:49:42.093 に答える
2

C++ はそのようには機能しません。共変の戻り値の型の考え方は、元の戻り値の型のサブクラスであるオブジェクトへの参照またはポインターに対してのみ機能します。

と書くときenum class MyEnum : intは、サブクラスを指定しているのではなく、MyEnum を int 型で実装することを指定しています。

次のことのみが許可されています。

class Base {
  public:
  virtual Base* foo() = 0;
};

class Derived : public Base {
  public:
  Derived* foo();
};
于 2012-11-08T03:09:11.797 に答える
2

enum MyEnum : intC++が共変であると認識しないのはなぜintですか?

そうではないため、派生クラス型のオブジェクトは暗黙的にパブリック基本型のオブジェクトとして扱われる可能性がありますが、厳密に型指定された列挙型は厳密に型指定されています。つまり、それらは暗黙のうちにその基になる型のオブジェクトとして扱われない可能性があり、そうは言っても、共変候補ではありません。

于 2012-11-08T04:28:37.690 に答える
2

enum最近 C++ に採用された型付きs。理想的な世界で s がすべきことはたくさんありenumます -- 定義された値を反復処理できなければならず、それらを代数にできるはずですclass。おそらく、あなたが求めているようなvirtual共変量を返す関数を作成できるはずです。enum

しかし、できません。

今、私たちができることは次のとおりです。

class Base {
public:
  virtual int getType() const { return 0; }
};

enum Bird : int { Chicken = 0, Duck = 1 };

class Derived: public Base {
public:
  Bird getBirdType() const { return static_cast<Bird>(getType()); }
  virtual int getType() const override { return Chicken; }
};

古いシグネチャ ( getType) は公開されたままですが、新しい関数 ( getBirdType) によって型が修正されたバージョンが得られます。

書くことができれば、世界はより良い場所になるかもしれませんが、Bird Derived::getType() const overrideライプニッツに同意しない限り、私たちはその世界に住んでいません. C++ に機能を追加すると、標準的な開発時間がかかり、コンパイラはそれを実装する時間がかかります。そのため、C++ に追加される機能は、市場のコンパイラでテスト済みであり、そのコストが利益と需要に見合うものである傾向があります。

本当にその機能が必要な場合は、C++ の標準化作業に参加することをお勧めします!

于 2012-11-08T03:18:43.657 に答える