C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[18]: 「typedef」について


(過去ログ 61 を表示中)

[トピック内 22 記事 (1 - 20 表示)]  << 0 | 1 >>

■34168 / inTopicNo.1)  「typedef」について
  
□投稿者/ 七篠 (33回)-(2009/03/21(Sat) 02:18:41)

分類:[C/C++] 

こんばんは。

自分はポインタ変数などを「typedef」なり「define」なりして使用しています。
自分と同じ型のポインタを持つ構造体なりクラスを作る時、「typedef」の場合は元の型が
すでに定義されていないといけないので、構造体・クラス宣言前に

class Test;
typedef Test    *PTEST;

class Test
{
};

などと対処できますが、クラスの中のクラスを「typedef」する場合は同じように対処できません。

class T{public: class Child;};
typedef T::Child	*PCHILD;	// エラー

class Test
{
public:
	class Child
	{
	};
};

typedef T::Child	*PCHILD;	// こちらはOK

クラス内クラスの「typedef」をあらかじめする方法はあるのでしょうか?
ご存知の方、いらっしゃいましたらアドバイスいただけると幸いです。

引用返信 編集キー/
■34169 / inTopicNo.2)  Re[1]: 「typedef」について
□投稿者/ επιστημη (1839回)-(2009/03/21(Sat) 05:13:39)
επιστημη さんの Web サイト
> class T{public: class Child;};
> typedef T::Child *PCHILD; // エラー

どんなエラーですか?
ウチ(VC++9)ではなんともないんですけど。

引用返信 編集キー/
■34171 / inTopicNo.3)  Re[2]: 「typedef」について
□投稿者/ 七篠 (34回)-(2009/03/21(Sat) 09:40:40)
No34169 (επιστημη さん) に返信

お返事ありがとうございます。

> どんなエラーですか?
「error C2011: 'T' : 'class' 型の再定義
'T' の宣言を確認してください。」というエラーメッセージが出ます。

> ウチ(VC++9)ではなんともないんですけど。
Visual Studio は 2005 です。
引用返信 編集キー/
■34172 / inTopicNo.4)  Re[3]: 「typedef」について
□投稿者/ Azulean (331回)-(2009/03/21(Sat) 09:50:00)
> Visual Studio は 2005 です。
Visual Studio 2005で試しましたが、C++、C++/CLIどちらでもコンパイルは通りました。

新規にプロジェクトを作成する所から、再現させるところまで一度確認してみませんか?
現状で提示されている情報では再現できないため、エラーからピンと来る人しか手助けができない状態です。
引用返信 編集キー/
■34173 / inTopicNo.5)  Re[3]: 「typedef」について
□投稿者/ επιστημη (1840回)-(2009/03/21(Sat) 10:15:14)
επιστημη さんの Web サイト
> 「error C2011: 'T' : 'class' 型の再定義
> 'T' の宣言を確認してください。」というエラーメッセージが出ます。

↓これだけで? んなハズないけどなー... エラー通り、Tを再定義してんじゃなくて?

class T{public: class Child;};
typedef T::Child *PCHILD;

引用返信 編集キー/
■34177 / inTopicNo.6)  Re[4]: 「typedef」について
□投稿者/ 七篠 (36回)-(2009/03/21(Sat) 15:50:12)
わかりづらい説明な上に記述に間違いがありました。
申し訳ありません。
正しくは以下のとおりです。

class T { public: class Child;};

typedef T::Child	*PCHILD;	// クラス T 内で Child のポインタを持たせるとき等のため

class T
{
public:
	class Child
	{
	};
};

引用返信 編集キー/
■34179 / inTopicNo.7)  Re[5]: 「typedef」について
□投稿者/ pluvia (5回)-(2009/03/21(Sat) 16:35:34)
> class T { public: class Child;};
> 
> typedef T::Child	*PCHILD;	// クラス T 内で Child のポインタを持たせるとき等のため
> 
> class T
> {
> public:
> 	class Child
> 	{
> 	};
> };
> 

T が二回定義されています。
T::Child の定義は、次のように書けます。

class T { public: class Child;};
typedef T::Child *PCHILD;

class T::Child // T::Child の定義。
{
};

コンパイルの確認は、Visual Studio 2005 で行いました。

引用返信 編集キー/
■34180 / inTopicNo.8)  Re[5]: 「typedef」について
□投稿者/ επιστημη (1841回)-(2009/03/21(Sat) 18:11:57)
επιστημη さんの Web サイト
> class T { public: class Child;};
> 
> typedef T::Child	*PCHILD;	// クラス T 内で Child のポインタを持たせるとき等のため
> 
> class T {
> public:
> 	class Child {
> 	};
> };

...再定義してんぢゃん。

引用返信 編集キー/
■34181 / inTopicNo.9)  Re[6]: 「typedef」について
□投稿者/ 七篠 (37回)-(2009/03/21(Sat) 22:14:53)
No34179 (pluvia さん) に返信

お返事ありがとうございます。

> T::Child の定義は、次のように書けます。
> 
> class T { public: class Child;};
> typedef T::Child *PCHILD;
> 
> class T::Child // T::Child の定義。
> {
> };
このような書き方があるのですね。 初めて知りました。


■No34180 (επιστημη さん) に返信
すみません、以下のような書き方ができるので、クラスの中のクラスに対しても
同じことがしたいと思ったのですが、そのまま同じではできないのですね。

class T;
typedef T 	*PT;

class T
{
 	PT 	pT;
};



pluvia さんのやり方でこのように書けました。

class T;
typedef T			*PT;

class T
{
public:
	PT		pT;

	class Child;
};

typedef T::Child	*PCHILD;

class T::Child
{
	PCHILD	pC;
};

今まで define と typedef による型定義の明確な区別がつかないでいたのですが、
define は使用前に定義されていればいいので一箇所にまとめて書けるが、
隠蔽することができない。(undef すれば可能ですが、手間がかかるし eclipse だと
入力候補に列挙されていしまう。 VS は逆に define が効いてるはずのスコープで
候補にでてこない)
typedef は定義前に定義対象が存在していないとダメ。 しかし、名前空間や
クラスのスコープが有効で、隠蔽ができる。

個人的には一箇所にまとめて書けて const も付けられる define を今まで多用していたのですが、
ライブラリなど内部でのみ使用したい型定義は typedef にしようと思います。

ところで、typedef したポインタ変数型に const を付けてキャストすると、const が認識
されないのか変換できません。
const 付きで typedef すると通るのですが…
個人的には const は型と一緒にしたくないので、今まではポインタ変数型は define にしていました。

const void pV;
//@--------------------------------------------------------
typedef char	*PCHAR;
reinterpret_cast<const PCHAR>(pV);	// 変換できない
									// これが理想

//A--------------------------------------------------------
typedef const char	*CPCHAR;
reinterpret_cast<CPCHAR>(pV);		// 変換できる

//B--------------------------------------------------------
#define PCHAR	char*
reinterpret_cast<const PCHAR>(pV);	// 変換できる

@のような形は typedef では不可能なのでしょうか?不可能であれば、Aの方法を使おうと
思います。

引用返信 編集キー/
■34182 / inTopicNo.10)  Re[7]: 「typedef」について
□投稿者/ επιστημη (1842回)-(2009/03/21(Sat) 22:56:07)
επιστημη さんの Web サイト
> ところで、typedef したポインタ変数型に const を付けてキャストすると、const が認識
> されないのか変換できません。
> const 付きで typedef すると通るのですが…

typedef char* PC;
であるとき、const PC の const は PC を修飾するので、その意味は
"const な (char*)" となります。
"(const char)の*" ではありません。

引用返信 編集キー/
■34209 / inTopicNo.11)  Re[8]: 「typedef」について
□投稿者/ 774RR (326回)-(2009/03/23(Mon) 09:11:09)
俺個人としては、ポインタ型を typedef するのはお勧めしない。
後輩諸氏には「絶対に使うな」と指導してる。

典型的システムハンガリアン記法であって、逆にとってもわかりにくくなると思うんだけど。

PCHILD a;
とあったとき、これがポインタなのかそうでないのかを P の有無で判断するわけ?
ならば CHILD* a; と書いて * の有無で判断しても同じぢゃん。
むしろ 非 Windows プラットフォームでは CHILD* a; のほうが一般的であり、
普通の技量があるプログラマなら CHILD* a; と書いたほうがわかりやすいと断言しておこう。

POINT p; はポインタなのかそうでないのか判断つかないし。

constness の問題も既に出てる。
MFC の型記述は LPSTR と LPCSTR を別に typedef しているわけだ。だけど
ポインタ自体が const なのか、ポインタが指す先が const なのか
記述方法自体に混乱を招くおそれを含んでいるわけで、そんな危険は冒さないほうがいい。
const とちゃんと記述するほうがわかりやすいと思う。

ちなみに constness の変換は const_cast を使う必要があるんだぞ
reinterpret_cast では constness が変換できないし、できてはならないことになっている。
引用返信 編集キー/
■34396 / inTopicNo.12)  Re[8]: 「typedef」について
□投稿者/ 七篠 (38回)-(2009/03/28(Sat) 09:38:07)
お返事ありがとうございます。

No34182 (επιστημη さん) に返信
> typedef char* PC;
> であるとき、const PC の const は PC を修飾するので、その意味は
> "const な (char*)" となります。
> "(const char)の*" ではありません。
なるほど、そういう違いがあったのですね。

No34209 (774RR さん) に返信
> constness の問題も既に出てる。
> MFC の型記述は LPSTR と LPCSTR を別に typedef しているわけだ。だけど
> ポインタ自体が const なのか、ポインタが指す先が const なのか
> 記述方法自体に混乱を招くおそれを含んでいるわけで、そんな危険は冒さないほうがいい。
> const とちゃんと記述するほうがわかりやすいと思う。
>
> ちなみに constness の変換は const_cast を使う必要があるんだぞ
> reinterpret_cast では constness が変換できないし、できてはならないことになっている。
個人的な好みになってしまうのですが、変数の後にアスタリスクを付けるのが好きじゃなかったので
define や typedef していたのですが、確かに typedef の方は個別に const 付けなくてはならないんですよね。
しかも変数名の一部になってしまうので強調表示もされず嫌でした。

趣味のプログラムでしか使っていない方法ですが、だいぶ書き込んでしまったので次プログラムを
書き始める時にアドバイスを参考に、今後この記法を続けるかやめるか考えさせていただきます。

皆さん、アドバイスありがとうございました!

P.S.
const の問題は define だとアスタリスクを付けたポインタ変数と変わらないので問題ないですよね…?


解決済み
引用返信 編集キー/
■34431 / inTopicNo.13)  Re[9]: 「typedef」について
□投稿者/ 774RR (334回)-(2009/03/29(Sun) 09:04:26)
#define は現代C++では非推奨なので、可能な限り使わないのが原則
# 使う必要があるときにはためらわずにつかう。
・「スコープ」の概念がない(ファイル全体で有効になってしまう)
・括弧を慎重に使わないと思わぬバグの原因になる
・異なる内容に再定義が可能

#define PCHAR char *
なんてのは世間一般的にはまず絶対に使われない記述だと思うぞ。
単純型へのポインタしか記述できないわけだし。
関数へのポインタや配列へのポインタなどを使いたくなったらどうするつもり?

未来永劫、世間一般にソースを公開することもしないし、他人のコードも読まないというなら別だが
・多数のプログラマが「採用している」記法(「採用することに決めた」記法)
・多数のプログラマが「採用しないことに決めた」記法
にはそれなりの理由があるわけだ。
その理由を知った上で、いや俺は独自の道を行くというならとめないし
理由も知らずに邪道とか茨の道とか行くのであれば、そりゃ遠回りなんではないかなーと思うけどさ。
解決済み
引用返信 編集キー/
■34660 / inTopicNo.14)  Re[10]: 「typedef」について
□投稿者/ 七篠 (39回)-(2009/04/05(Sun) 06:10:15)
No34431 (774RR さん) に返信

> ・多数のプログラマが「採用している」記法(「採用することに決めた」記法)
> ・多数のプログラマが「採用しないことに決めた」記法
> にはそれなりの理由があるわけだ。

確かにそうですね。
それにポインタ変数や参照変数を typedef や define しないとなると、今まで述べたような const や
スコープの問題に悩む必要がなくなりますね。

ありがとうございました!
引用返信 編集キー/
■34664 / inTopicNo.15)  Re[11]: 「typedef」について
□投稿者/ ちゃっぴ (224回)-(2009/04/05(Sun) 10:52:26)
ちゃっぴ さんの Web サイト
2009/04/05(Sun) 10:56:46 編集(投稿者)

とはいえ、Win32 を扱うとなると

typedef const WCHAR *LPCWSTR

上記のようなものばっか出てくるので、扱うものによって変わってくるんじゃないかと思います。
Win32 をよく使うのであれば Win32 のような system Hungarian notation で統一させるのも一手かも。
引用返信 編集キー/
■34845 / inTopicNo.16)  Re[12]: 「typedef」について
□投稿者/ 七篠 (40回)-(2009/04/11(Sat) 14:01:52)
お返事ありがとうございます。

No34664 (ちゃっぴ さん) に返信
> 2009/04/05(Sun) 10:56:46 編集(投稿者)

> 上記のようなものばっか出てくるので、扱うものによって変わってくるんじゃないかと思います。
> Win32 をよく使うのであれば Win32 のような system Hungarian notation で統一させるのも一手かも。

環境で定義されている変数はそれに従うということでしょうか?
たとえば「DWORD」型を格納する変数は「unsigned long」型でも同義ですが、「DWORD」型として
宣言しておくみたいな感じで。
引用返信 編集キー/
■34858 / inTopicNo.17)  Re[13]: 「typedef」について
□投稿者/ ちゃっぴ (227回)-(2009/04/12(Sun) 20:41:10)
ちゃっぴ さんの Web サイト
No34845 (七篠 さん) に返信
> 環境で定義されている変数はそれに従うということでしょうか?
> たとえば「DWORD」型を格納する変数は「unsigned long」型でも同義ですが、「DWORD」型として
> 宣言しておくみたいな感じで。

それはごく当たり前のことのような。
まあ、無いと思うけど、DWORD の定義が変更になったらどうなるか?とか。

この手の規約って、統一させることによる可読性の向上というのが主目的だと思うので、わかりやすく統一されていれば問題ないと個人的には思っています。


引用返信 編集キー/
■34863 / inTopicNo.18)  Re[14]: 「typedef」について
□投稿者/ 倉田 有大 (548回)-(2009/04/13(Mon) 02:00:01)
2009/04/13(Mon) 02:00:26 編集(投稿者)

typedef使い方わすれちゃった

class Test
{
}

typedef Tests List<Test>;

C#でこんな事したいよう(ノ_・、)

class Tests : List<Test>
{
}

こうやって使うのかな。


public class Tests : IEnumerable
{
private ArrayList tests = new ArrayList();
}

こんな感じで実装しましたが。今だと、どうやるのがいいんだろう。
引用返信 編集キー/
■34867 / inTopicNo.19)  Re[15]: 「typedef」について
□投稿者/ あんどちん (47回)-(2009/04/13(Mon) 09:52:26)
No34863 (倉田 有大 さん) に返信
> 2009/04/13(Mon) 02:00:26 編集(投稿者)
> typedef Tests List<Test>;
>
> C#でこんな事したいよう(ノ_・、)
>
using Tests = List<Test>;

では要求を満たせないでしょうか?

引用返信 編集キー/
■34872 / inTopicNo.20)  Re[16]: 「typedef」について
 
□投稿者/ 倉田 有大 (549回)-(2009/04/13(Mon) 11:28:07)
2009/04/13(Mon) 11:43:26 編集(投稿者)
2009/04/13(Mon) 11:28:31 編集(投稿者)

>using Tests = List<Test>;

あー、ぐぐったら、このやり方を見つけました。

どうなんでしょう?これ
なんか、usingをこんな使い方するのは違和感を感じるのですが、慣れたらそうでもないのかな?

ところでList<>って継承しちゃだめだったんですねー知りませんでした。

後、スレチになりますが、List()は各要素の削除時に
Dispose()メソッドなんて呼んでくれませんよね?
List<T>のTのクラスにアンマネージドのリソースがあった場合どうするのかな。デストラクタに開放処理をかいて、開放してくれるの気長に待つ?

各要素を削除時にDisposeを呼びたいときはCollection(T)
を継承して、Removeなどオーバーライドして、自分でDispose処理入れるのかな。
引用返信 編集キー/

次の20件>
トピック内ページ移動 / << 0 | 1 >>

管理者用

- Child Tree -