enum型 が戻り値に設定できない – プログラミング – Home

enum型 が戻り値に設定できない
 
通知
すべてクリア

[解決済] enum型 が戻り値に設定できない

固定ページ 1 / 2

pianyi
 pianyi
(@pianyi)
ゲスト
結合: 21年前
投稿: 17
Topic starter  

はじめまして。
pianyiと申します。

下記のようなenumを宣言し、getter/setterを作ったのですが、getterでエラーが発生し
ます。
原因がさっぱり解りません。間違いや修正のヒントなど頂け無いでしょうか。

エラー内容:
error C2143: 構文エラー : ';' が 'CAiueoDlg::GetType' の前にありません。

ヘッダのソース:
class CAiueoDlg : public CDialog
public:
enum TYPE {
A,
B,
C,
D,
E,
F,
G
};
void SetType(TYPE tmp);
TYPE GetType();

private:
TYPE m_Type;
};

ソース:
#include AiueoDlg.h

TYPE CAiueoDlg::GetType()
{ return m_Type; }
void CAiueoDlg::SetType(TYPE type)
{ m_Type = type; }

GetType() の戻り値をintにするとビルドは通るのですが、
別クラスでGetした値がintになってしまうので、enumを使っている意味が無くなってしま
います。

Java や C# と同じ感覚で使用してはいけないのでしょうか?

よろしくお願いします。

開発環境:
OS:Windows XP SP3
ツール:VS 2008 VC++ MFC


引用未解決
トピックタグ
蒼の洞窟
 蒼の洞窟
(@蒼の洞窟)
ゲスト
結合: 12年前
投稿: 28
 

単に、CAuieoDlgのクラス外の記述であるときに、TYPEが何かわからないから
エラーが出るだけのようです。

CAiueoDlg::TYPE CAiueoDlg::GetType()
{ return m_Type; }
void CAiueoDlg::SetType(CAiueoDlg::TYPE type)
{ m_Type = type; }

とすればイケると思います。


返信引用
pianyi
 pianyi
(@pianyi)
ゲスト
結合: 21年前
投稿: 17
Topic starter  

蒼の洞窟 さん

ご回答ありがとうございます。

確かに…
Getterの1行を「CAiueoDlg::TYPE CAiueoDlg::GetType()」に変更することによりエラー
は無くなりました。

「CAuieoDlgのクラス外の記述」という事は、ヘッダとソースファイルは、コンパイラ内
で別クラスと解釈されるって事なんでしょうか…
戻り値は中括弧の外だからグローバル解釈されるのかな…?

どちらにせよ、ありがとうございます。
本当に助かりました。m(_ _)m

以下愚痴です。
Setterには付け無くてもエラーにはならないのに…
ヘッダーにも書く必要が無いのに…
ひどい…(泣)


返信引用
仲澤@失業者
(@uncle_kei)
Prominent Member
結合: 5年前
投稿: 828
 

ん?
解決しちゃってますけど、明確に定義宣言すれば使えますよね。

class XXXX
{
public:
typedef enum TYPE {
A,B,C,D,E,F,G
}TYPE;
void SetType(TYPE ex_Type){ m_Type = ex_Type;}
TYPE GetType(){ return m_Type;}

private:
TYPE m_Type;
};
//----------------
XXXX x;
x.SetType( XXXX::D);
XXXX::TYPE t = x.GetType();

とか。
要は、中途半端な「タグ無し」がまずいだけのような気がするのですが(vv;)。
まぁ、厳密ではありますが、あんまり便利感がありせんけどね。


返信引用
蒼の洞窟
 蒼の洞窟
(@蒼の洞窟)
ゲスト
結合: 12年前
投稿: 28
 

>>Setterには付け無くてもエラーにはならないのに…
これは、
>>CAiueoDlg::SetType
の段階で、CAiueoDlgのSetTypeというメンバ関数と限定されるので、
その後ろに来るTYPEはCAiueoDlgの型とみなされるんでしょう。

単純な、Set/Getならinlineにしちゃうとか。(仲澤@失業者さんの記述通り)


返信引用
pianyi
 pianyi
(@pianyi)
ゲスト
結合: 21年前
投稿: 17
Topic starter  

仲澤@失業者 さん

回答ありがとうございます。

> 解決しちゃってますけど、明確に定義宣言すれば使えますよね。
これは、inline で記述してるから出来てる気がしますが、違うのでしょうか?
試してみたのですがやはりエラーになります…
何が違うんだろう…orz

蒼の洞窟 さん

確かにinline にしてしまうのも手ですが、JavaやC#を長年やってるとソースが散らばる
のが嫌なんですよね…
特に今回は、getterは単純なんですが、setterは別処理をはさむのでinlineにはしたくな
いです。

ここまで来ると開発者や開発チームの規約になっちゃいますね。


返信引用
仲澤@失業者
(@uncle_kei)
Prominent Member
結合: 5年前
投稿: 828
 

え~と、TYPE型はclass XXXXの内部定義型なので、
「お外で使う場合も所有者の明示」が必要です。

class XXXX{
public:
typedef enum TYPE {
A,B,C,D,E,F,G
}TYPE;
// void SetType(TYPE ex_Type){ m_Type = ex_Type;}
// TYPE GetType(){ return m_Type;}
void SetType(TYPE ex_Type);
TYPE GetType();
private:
TYPE m_Type;
};

void XXXX::SetType(TYPE ex_Type){ m_Type = ex_Type;}
XXXX::TYPE XXXX::GetType(){ return m_Type;}


返信引用
仲澤@失業者
(@uncle_kei)
Prominent Member
結合: 5年前
投稿: 828
 

追記すると、
こういった、(厳密さは魅力だが)やや間抜けな記述になるので、
自分は可能な限り*.cppにコードは書きませんです(vv;)。

*.cppにコードすると「インライン展開されないことが確定」する
以外には、あまりメリットが見いだしづらいと考えます。
*.hに記述するメリットはいっぱいありますけどね(笑)。


返信引用
tetrapod
 tetrapod
(@tetrapod)
ゲスト
結合: 21年前
投稿: 830
 

なんだか文句たらたらのようだけど、言語仕様書に明記されている「仕様」だし
文句言うくらいなら(クラス内 enum を or C++ を)使わなきゃいい。

struct foo {
 enum bar { ... };
 bar value;
 void set(bar x);
 bar get() const;
}; // とあるとき

・作られる enum は foo::bar という名前となる (決して bar ではない)
・特定の文脈では foo を明示しない場合でも foo に属する識別子を先に見に行く
だけのこと。
後者の規則がないと foo のメンバーである識別子 value を探してくれないので不便。

void foo::set(bar x) { value=x; } // のような、
非インライン関数定義をコンパイラが処理する際の規則は、仕様書に定められている。

それによるとこの例では、開き括弧を読み取った時点で、
foo のメンバー関数 foo::set の定義であるとコンパイラが識別できる。そのため、
この開き括弧以後は foo の中の識別子を lookup に含める規則となっている。
なので bar の名前検索の際には foo:: を(自動的に)補うことができるため
上記 setter はコンパイルエラーにならない。
蒼の洞窟氏の指摘はそういうこと。
もちろん void foo::set(foo::bar x) { ... } と書いても問題ない。

一方で bar foo::get() const { return value; } という非インライン関数定義は
コンパイラが bar を読み取った時点ではまだ foo のメンバ関数定義と判断できない。
上記と同様、開き括弧を読み取った後であれば foo:: を補えるが、
それを既に読み取ったソースコード部分まで遡って適用しない規則。
なので 上記 getter の bar は不明な識別子であるエラーとなる。
foo::bar foo::get() const { return value; } なら OK.


返信引用
yukihiro
 yukihiro
(@yukihiro)
ゲスト
結合: 22年前
投稿: 24
 

> なんだか文句たらたらのようだけど、言語仕様書に明記されている「仕様」だし
> 文句言うくらいなら(クラス内 enum を or C++ を)使わなきゃいい。

横からすみませんが、
文句ではなく疑問ですよね。

疑問を持つことは理解するためのファーストステップであり、
それを批判するのはおかしいと思います。

仮に文句だったとしても、
誰も文句も言わず与えられた仕様に甘んじているだけでは
何の進歩もないでしょう。

#トピックと関係ない話で申し訳ありません。


返信引用
pianyi
 pianyi
(@pianyi)
ゲスト
結合: 21年前
投稿: 17
Topic starter  

仲澤@失業者 さん
なるほど!
*.h に全部書いちゃうって言うのも手ですね。
Javaとか、C#に近くなって良いかも…(やってみないと解らないけど…)
「ヘッダ = 実装なし」って言う固定概念が…
ん?*.cppファイルがいらない子になっちゃう(笑

tetrapod さん
ご回答ありがとうございます。
蒼の洞窟さんの補足&詳細説明ありがとうございます。

yukihiro さん
ありがとうございます。
トピックと関係ないですが、ありがとうございます。

皆さん、ありがとうございました。


返信引用
bun
 bun
(@bun)
ゲスト
結合: 24年前
投稿: 761
 

順を追って説明すると、以下の通りです ^^

以下のように宣言すると、
class CAiueoDlg : public CDialog
public:
enum TYPE {
};
};

enumの型は言語仕様的に
CAiueoDlg::TYPE
です。

だから、
enum TYPE {
};
を直後に書いても、ちゃんと、グローバルスコープのenum とみなされ、
重複定義にならず、コンパイルが通ります。
(グローバルenumと、クラススコープ付きenumは違うつうことですね)

で、以下のコードがコンパイルエラーにならないのは、
class CAiueoDlg : public CDialog
public:
enum TYPE {
};
void SetType(TYPE tmp);
TYPE GetType();
};
SetType()関数が、CAiueoDlgクラスのメンバ関数であるから。

同一クラス内だから、「CAbcdeDlg::」の省略を許してくれているわけで、
ひどいどころか親切設計な訳です ^^


返信引用
επιστημη
 επιστημη
(@επιστημη)
ゲスト
結合: 21年前
投稿: 600
 

C++11 ならこう↓書けるす。

class Foo {
public:
enum TYPE { A,B,C,D,E,F,G };
void SetType(TYPE tmp);
TYPE GetType();

private:
TYPE m_Type;
};

auto Foo::GetType() -> TYPE { return m_Type; }
auto Foo::SetType(TYPE type) -> void { m_Type = type; }


返信引用
pianyi
 pianyi
(@pianyi)
ゲスト
結合: 21年前
投稿: 17
Topic starter  

bun さん
ご回答ありがとうございます。

>>ひどいどころか親切設計な訳です ^^
今回のルール?を知らない立場からすると、引数と戻り値の 両方省略可能 または 両方省略不可
とした方が、「統一性があって解りやすい。」と思った次第です。
なので、親切設計と言われると「小さな親切大きな…」と思いました。

確かにグローバル enum との兼ね合いがあるので、仕様設計者?も悩んだ結果なのでしょう。

しかし…
public の enum は、グローバル化してしまえば良いのか…?
private の enum なら、getter/setterなんて不要なんだし…
protected の enum が問題になるのか…
今回は使わないけど、悩ましい…

επιστημη さん
ご回答ありがとうございます。

C++11って、Visual Studio 2012?から組み込まれてる奴ですよね?

戻り値をautoにして、後ろに書くとは新しい発想ですね。
確かに、私の愚痴は解消されてますが、コーディング者泣かせですね(笑
いつの日かそれが当たり前になるのかなぁ。


返信引用
επιστημη
 επιστημη
(@επιστημη)
ゲスト
結合: 21年前
投稿: 600
 

> C++11って、Visual Studio 2012?から組み込まれてる奴ですよね?

このコード、VS2010(vc10)でも通るですよ。


返信引用
固定ページ 1 / 2

返信する

投稿者名

投稿者メールアドレス

タイトル *

プレビュー 0リビジョン 保存しました
共有:
タイトルとURLをコピーしました