ページ 11

メンバ関数の引数に自分と同じ型を設定したい

Posted: 2014年4月19日(土) 12:18
by jay
やりたいことはタイトル通りですが、以下のような構造体を作ろうとしました

コード:

//int型2次元座標
typedef struct
{
	int x;	//X座標
	int y;	//Y座標

	//値の加算
	//引数:加算する値を設定したPos_t構造体
	void Add(Pos_t SetPos)
	{
		x += SetPos.x;
		y += SetPos.y;
	}
	//値の加算
	//引数:加算する値を設定したint型データ(x, y)
	void Add(int sx, int sy)
	{
		x += sx;
		y += sy;
	}
}Pos_t;
コンパイルすると1つめのAdd関数の所でエラーが出ます
エラー 1 error C2061: 構文エラー : 識別子 'Pos_t'

これはPos_tの定義がないからダメって言ってるのだと推測してます
つまりメンバ関数の引数にそのまま自分自身の型を渡すことはできないのでしょうか?

渡す方法があれば教えてください
ちなみにエディターは Visual C++ 2010 Express です

Re: メンバ関数の引数に自分と同じ型を設定したい

Posted: 2014年4月19日(土) 12:31
by Tatu
自己参照構造体のやり方を使えばできそうな気がしますがどうでしょうか?

Re: メンバ関数の引数に自分と同じ型を設定したい

Posted: 2014年4月19日(土) 13:50
by softya(ソフト屋)
C++なんですから、これではダメでしょうか?

コード:

struct Pos_t
{
    int x;  //X座標
    int y;  //Y座標
 
    //値の加算
    //引数:加算する値を設定したPos_t構造体
    void Add(Pos_t SetPos)
    {
        x += SetPos.x;
        y += SetPos.y;
    }
    //値の加算
    //引数:加算する値を設定したint型データ(x, y)
    void Add(int sx, int sy)
    {
        x += sx;
        y += sy;
    }
};

Re: メンバ関数の引数に自分と同じ型を設定したい

Posted: 2014年4月19日(土) 13:53
by Milla
コンパイラは上から順にコンパイルするんですが、
void Add(Pos_t SetPos)
この時点でtypedef構文が終わってません。
なのでPos_tが何なのかコンパイラには理解できません。

コード:

//int型2次元座標

typedef struct _Pos_t Pos_t;

struct _Pos_t
{
	int x;  //X座標
	int y;  //Y座標

	//値の加算
	//引数:加算する値を設定したPos_t構造体
	void Add(Pos_t SetPos)
	{
		x += SetPos.x;
		y += SetPos.y;
	}
	//値の加算
	//引数:加算する値を設定したint型データ(x, y)
	void Add(int sx, int sy)
	{
		x += sx;
		y += sy;
	}
};

Re: メンバ関数の引数に自分と同じ型を設定したい

Posted: 2014年4月19日(土) 14:01
by Milla
typedef struct _NAME{
}NAME;

は構造体の宣言と構造体の定義と型定義を同時に行っていることを忘れてはいけません。

構造体の宣言
struct _NAME;

構造体の宣言かつ定義
struct _NAME{
};

型定義
typedef struct _NAME NAME;

soft屋さんの書いているとおり、C++では構造体はすべてがデフォルトでパブリックなクラスなので
class NAME;とかいてNAME objNAMEと変数を作れるように
struct NAME;とかいてNAME objNAMEと変数を作れます。

Re: メンバ関数の引数に自分と同じ型を設定したい

Posted: 2014年4月19日(土) 14:25
by usao
_Pos_t だとか _NAME とかいうのは予約語の規則に違反してますよ.
オフトピック
何やらこの掲示板では
typedef struct { ... } name; のように構造体を無名にする書き方をよく見かける気がしますが
そうすることで何かメリットあるんでしょうか? 扱い難いだけだと思うのすが.

Re: メンバ関数の引数に自分と同じ型を設定したい

Posted: 2014年4月19日(土) 14:29
by softya(ソフト屋)
オフトピック
typedef struct { ... } name; のように構造体を無名にする書き方をよく見かける気がしますが
まぁ、前方参照しない限りにおいては構造体名は不要なので付ける必要のない名前を付けるのは無駄手間という考え方もあると思います。

Re: メンバ関数の引数に自分と同じ型を設定したい

Posted: 2014年4月19日(土) 15:15
by Tatu
>>usaoさん,softya(ソフト屋)さん
>No:6,No:7のOfftopic
それについてはDixqさんに聞いたほうがよいかと思います。

追記:
構造体のタグ名を下線で始めることについて

株式会社きじねこのC/C++迷信集
[迷信] 構造体のタグ名は下線で始める
http://www.kijineko.co.jp/tech/supersti ... score.html

に書かれていました。

Re: メンバ関数の引数に自分と同じ型を設定したい

Posted: 2014年4月19日(土) 15:30
by naohiro19
Milla さんが書きました:typedef struct _NAME{
}NAME;

は構造体の宣言と構造体の定義と型定義を同時に行っていることを忘れてはいけません。

構造体の宣言
struct _NAME;

構造体の宣言かつ定義
struct _NAME{
};

型定義
typedef struct _NAME NAME;

soft屋さんの書いているとおり、C++では構造体はすべてがデフォルトでパブリックなクラスなので
class NAME;とかいてNAME objNAMEと変数を作れるように
struct NAME;とかいてNAME objNAMEと変数を作れます。
[迷信] 構造体のタグ名は下線で始める | 株式会社きじねこ
このコードの動作は未定義だということをご存知でしょうか? _FOO のように、下線(アンダースコア、アンダーバー)で始まり、下線または大文字が続く識別子は「予約済み識別子」です。予約済み識別子というのは、規格がライブラリに使うか、処理系が作業用または拡張用に使うために予約されている識別子で、それらをユーザープログラムで使用することはできません(使用した場合の動作は未定義です)。

Re: メンバ関数の引数に自分と同じ型を設定したい

Posted: 2014年4月19日(土) 17:05
by jay
回答ありがとうございます

今回はMillaさんが教えて下さった方法で思い通りの実装をすることができました

コード:

typedef struct 2DPosition_Type_t Pos_t;

//int型2次元座標
struct 2DPosition_Type_t
{
	int x;	//X座標
	int y;	//Y座標

	//値の加算
	//引数:加算する値を設定したPos_t構造体
	void Add(Pos_t SetPos)
	{
		x += SetPos.x;
		y += SetPos.y;
	}
	//値の加算
	//引数:指定方向のDir定数配列
	void Add(const int Add[2])
	{
		x += Add[0];
		y += Add[1];
	}
};
ご協力して下さった皆様、ありがとうございます。


>usaoさん
typedef struct { ... } name; のように構造体を無名にする書き方をよく見かける気がしますが
そうすることで何かメリットあるんでしょうか? 扱い難いだけだと思うのすが.
Tatuさんがおっしゃる通り、これはDixqさんに聞いた方がいいと思います。
僕も龍神録の館からゲームプログラミングを学んだクチで
今は「このやり方が自分にとって分かりやすいから」と言う理由でこの書き方をしているだけですので(苦笑)
(と言ったら理屈を理解せずに使ってるのか、って怒られそうですけど)

Re: メンバ関数の引数に自分と同じ型を設定したい

Posted: 2014年4月19日(土) 17:49
by milla
迷信だったんですか
これは申し訳ない

ただ、タイプデフで同じ名前にすると
vsのインテリセンスで衝突したはずですので
ソフト屋さんの書き方が一番安全かと思われます。

Re: メンバ関数の引数に自分と同じ型を設定したい

Posted: 2014年4月20日(日) 19:03
by Mana
タグ名と型名を同じにすると問題があるというのも迷信だね。

コード:

struct Hoge {
    Hoge(const Hoge &hoge);
};

コード:

typedef struct Hoge Hoge;
struct Hoge {
    Hoge *hoge;
};
typedef structの無名構造体は迷信の普及に貢献してるね。