2016-06-29 6 views
0

私は最近、小さなプロジェクトで作業するときに奇妙なエラーセットを作成しました。列挙型メンバーがクラス名と矛盾します

#include <memory> 

enum derivedtype {B, C}; 

//abstract class 
class A{}; 

class B : public A 
{}; 
class C : public A 
{}; 

int main() 
{ 
    { 
    std::unique_ptr<A> myb(new B); 
    std::unique_ptr<A> myc(new C); 
    } 
} 

このコンパイラエラーを生成します:これは、基本的にそれを引き起こしたコードだった

enumclasserror.cpp: In function ‘int main()’: 
    enumclasserror.cpp:15:30: error: ‘B’ does not name a type 
    std::unique_ptr<A> myb(new B); 
         ^
    enumclasserror.cpp:16:30: error: ‘C’ does not name a type 
    std::unique_ptr<A> myc(new C); 

修正は、新規の後、クラスのキーワードを追加しました:今

std::unique_ptr<A> myb(new class B); 

列挙型を元のコードのabstactクラスのヘッダファイルにインクルードされていましたが(それはスポットするのがさらに難しくなりました)、それは気にしませんでした。列挙型のメンバーがインスタンスの作成を失敗させる可能性があるとは想像もできませんでした。そのバグを発見するのに、文字通り時間がかかりました。誰も私になぜそれが起こるか説明することができますか?新しいことはenumsで意味をなしますか?

P.S:エラーは、クラスのキーワードを提案打ち鳴らすを使用しています同僚によって発見されました。あなたが見ることができるように私のUbuntuの標準C++コンパイラは、私はあなたがここに期待他に何かわからない

+0

「バグ」と「インスタンス生成の失敗」と言うと、実行時の問題のように聞こえるだけです。あなたが経験した唯一の問題は、バグではなくコンパイラエラーです。 –

+0

@TrevorHickey:コンパイラエラーはバグです。 –

+0

Wikipediaは、バグに関して「間違った、予期しない結果を引き起こす、または意図しない動作をするコンピュータプログラムやシステムのエラー、欠陥、不具合、または障害」と定義しています。 – pingul

答えて

5

BenumからクラスBになります。標準のセクション3.3.10がを隠す名前のルールを説明します

A class name (9.1) or enumeration name (7.2) can be hidden by the name of a variable, data member, function, or enumerator declared in the same scope. If a class or enumeration name and a variable, data member, function, or enumerator are declared in the same scope (in any order) with the same name, the class or enumeration name is hidden wherever the variable, data member, function, or enumerator name is visible.

言語設計者は、優先順位のルールを設定するために必要なので、彼らはenum定数名が勝つべきであると決定しました。このルールは任意であると思われ、おそらくC標準のいくつかの古いルールの後にモデル化されます。しかし、それは標準の一部なので、すべてのコンパイラがそれに従わなければなりません。

それはenumメンバーと衝突するクラス名を作ることは非常に悪い考えであることは言うまでもないです。この問題を解決する最善の方法は、クラスの名前を変更することです。

+0

ありがとうございます!これはまさに私が望んでいた答えのようなものでした;)私が前に言ったように、私には明らかでない名前がこの場合にも当てはまると思います。それは同じ名前を持っています)は確かに非常に悪い考えです。 – jaaq

+0

例外がある場合を除いて、名前の隠蔽が発生します。ここに例外があると、あなたのコードはうまくいきました!この質問はとても空想的です:) –

2

...カントーませんでした。

はまず、あなたはBCという名前の積分定数を導入しました。もちろん、これらはnewできません。それはnew 42のようなものです。

次に、同じ名前の型を導入しました。さて、罰金、それは許されていますが、あなたが発見したように、これらを使用するためにあなたが今、class Bclass C(またはstruct Bstruct C)としてそれらを参照する必要があります。

は異なるものに同じ名前を使用しないでください。

+0

OPは、* new-expression *の* type-id *で発生する名前検索で、非タイプ名が無視されることを期待している可能性があります。明らかに、それは起こらない。 – Brian

+0

@Brian:OPが間違っていて、すでにこれを発見しています。正直言ってここに答えてみることは本当にありません。とにかく私はそれに答えた故意に皮肉なことだと思います... –

+0

質問はこの答えを意味します。 –

関連する問題