C++におけるポインタの質問

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
Spika

C++におけるポインタの質問

#1

投稿記事 by Spika » 10年前

コード:

#include "main.h"
using namespace std;

void update(Charactor* pc,Charactor* pe){
	cout << " X " <<pc->GetPointX() << " Y " <<pc->GetPointY() << endl;
}

//object
void Object_Base::Initialize(){
	cout<<"Object_Base I"<<endl;
}
void Object_Base::Update(){
	cout<<"Object_Base U"<<endl;
}
void Object_Base::Draw(){
	cout<<"Object_Base D"<<endl;
}
void Object_Base::Finalize(){
	cout<<"Object_Base F"<<endl;
}

//charactor
Charactor::Charactor(int x,int y){
	pos.x = x;
	pos.y = y;
}
void Charactor::Initialize(){
	cout<<"Charactor I"<<endl;
}
void Charactor::Update(){
	cout<<"Charactor U"<<endl;
}
void Charactor::Draw(){
	cout<<"Charactor D"<<endl;
}
void Charactor::Finalize(){
	cout<<"Charactor F"<<endl;
}
t_pos Charactor::GetPoint(){
	cout<<"Charactor GetPoint"<<endl;
	return pos;
}
int Charactor::GetPointX(){
	cout<<"Charactor GetPointX"<<endl;
	return pos.x;
}
int Charactor::GetPointY(){
	cout<<"Charactor GetPointY"<<endl;
	return pos.y;
}
void Charactor::PrintData(int x){
	cout << "Charactor Data" << x <<endl;
}

void* Charactor::GetPointer(){
	return this;
}

//player
Player::Player(int x,int y){
	pos.x=x;
	pos.y=y;
}
void Player::Initialize(){
	cout<<"Player I"<<endl;
}
void Player::Update(){
	cout<<"Player U"<<endl;
}
void Player::Draw(){
	cout<<"Player D"<<endl;
}
void Player::Finalize(){
	cout<<"Player F"<<endl;
}
t_pos Player::GetPoint(){
	cout<<"Player GetPoint"<<endl;
	return pos;
}
int Player::GetPointX(){
	cout<<"Player GetPointX"<<endl;
	return pos.x;
}
int Player::GetPointY(){
	cout<<"Player GetPointY"<<endl;
	return pos.y;
}

//Enemy
Enemy::Enemy(int x,int y){
	pos.x=x;
	pos.y=y;
}

void Enemy::Initialize(){
	cout<<"Enemy I"<<endl;
}
void Enemy::Update(){
	cout<<"Enemy U"<<endl;
}
void Enemy::Draw(){
	cout<<"Enemy D"<<endl;
}
void Enemy::Finalize(){
	cout<<"Enemy F"<<endl;
}

t_pos Enemy::GetPoint(){
	cout<<"Enemy GetPoint"<<endl;
	return pos;
}

int Enemy::GetPointX(){
	cout<<"Enemy GetPointX"<<endl;
	return pos.x;
}

int Enemy::GetPointY(){
	cout<<"Enemy GetPointY"<<endl;
	return pos.y;
}

void* Enemy::GetPointer(){
	return this;
}

int main(){
	Charactor *charactor[5];
	charactor[0] = new Player(10,20);
	charactor[1] = new Enemy(25,30);
	charactor[2] = new Player(75,51);
	charactor[3] = new Enemy(54,41);
	charactor[4] = new Player(25,30);

	charactor[0] = (Charactor*)(charactor[1]->GetPointer());

	for(int i = 0;i < 5;i++){
		charactor[i]->Initialize();
		charactor[i]->Update();
		cout<<charactor[i]->GetPointX()<<endl;
		cout<<charactor[i]->GetPointY()<<endl;
		charactor[i]->Draw();
		charactor[i]->PrintData(charactor[i]->GetPointX());
		cout << "--------------------------" << endl;
	}
}
この時、void*型からcharactorにキャストしていますが、プログラムとしてよいのでしょうか?
また、void*は汎用ポインタときき使ってみましたが、どういう振る舞いをするのでしょうか??
実行例ではきちんと動いていたので、エラーがあるなどでは、有りません。

Spika

Re: C++におけるポインタの質問

#2

投稿記事 by Spika » 10年前

名前を固定するため、ここへ登録したのですが、パスを忘れたのか間違えていたのかはいれなくなり、メアドも一部逆にしてしまっているようで、名前を変えざる得なくなってしましました。
前の名前はBoneです。

アバター
usao
記事: 1889
登録日時: 11年前

Re: C++におけるポインタの質問

#3

投稿記事 by usao » 10年前

>この時、void*型からcharactorにキャストしていますが、プログラムとしてよいのでしょうか?

そもそも何故void*を経由したのかが謎ですし,
よいか? と問われると よくはない という感じでしょうか.↓のような雰囲気ですので.


>また、void*は汎用ポインタときき使ってみましたが、どういう振る舞いをするのでしょうか??

void* にした時点で型の情報は失われます.
Enemy::GetPointer()が返すのは,型が不明な 謎の値 です.
で,それを
Charactor* 型に強引にキャストして(コンパイラに対して「この値は Charactor* 型だと思って」と指示して)やれば
Charactor*型として振舞おうとするわけです.
提示コードでは その値が本来は Enemy* 型な値で,さらに,(おそらく)Enemy型はCharactorからの派生クラスなのでしょうから
結果として うまいこと動いている, ということです.
(つまり,void*を使った場合,このように「本当にまともな型に」キャストしてやる必要がある.
 コンパイラ側は,それが 本当に大丈夫なキャストなのかどうかを判定できないので,自己責任というか.)

アバター
usao
記事: 1889
登録日時: 11年前

Re: C++におけるポインタの質問

#4

投稿記事 by usao » 10年前

で,そういう
「うっかり間違うと何が起こるかわからないような危ない橋」をわざわざ渡る必要があるのかどうか?
ということを考えるべきかな,と思います.

あと,コードに関していえば,
・そもそも GetPointer() というメソッドの必要性 が謎です.
 加えて,その戻り値がわざわざvoid*というのが更なる謎です.
 このメソッドの意図がわかりません.
・135行目は 129行目でcharactor[0]に入れた値を上書きしてしまうので,いろいろと問題ありですよね.

Spika

Re: C++におけるポインタの質問

#5

投稿記事 by Spika » 10年前

usao さんが書きました:>この時、void*型からcharactorにキャストしていますが、プログラムとしてよいのでしょうか?

そもそも何故void*を経由したのかが謎ですし,
よいか? と問われると よくはない という感じでしょうか.↓のような雰囲気ですので.


>また、void*は汎用ポインタときき使ってみましたが、どういう振る舞いをするのでしょうか??

void* にした時点で型の情報は失われます.
Enemy::GetPointer()が返すのは,型が不明な 謎の値 です.
で,それを
Charactor* 型に強引にキャストして(コンパイラに対して「この値は Charactor* 型だと思って」と指示して)やれば
Charactor*型として振舞おうとするわけです.
提示コードでは その値が本来は Enemy* 型な値で,さらに,(おそらく)Enemy型はCharactorからの派生クラスなのでしょうから
結果として うまいこと動いている, ということです.
(つまり,void*を使った場合,このように「本当にまともな型に」キャストしてやる必要がある.
 コンパイラ側は,それが 本当に大丈夫なキャストなのかどうかを判定できないので,自己責任というか.)
Charactorクラスのポインタに生成したPlayerとEnemyのアドレスを、別のクラスに持ち込めないかとおもったのですが、その場合戻り値の値はPlayer*とEnemy*と始めに書いてやらないといけないと、思っているため、オーバーライドできるように共通の型void*型へ一時的にいれてキャストしてやればなんとかなるのでは?と思ったのですが、void*をCharactor*にかえても同様に動くのでしょうか?
そもそもthisポインタとはどこのアドレスを渡しているのかが、少しわからないところがあります

Spika

Re: C++におけるポインタの質問

#6

投稿記事 by Spika » 10年前

usao さんが書きました:で,そういう
「うっかり間違うと何が起こるかわからないような危ない橋」をわざわざ渡る必要があるのかどうか?
ということを考えるべきかな,と思います.

あと,コードに関していえば,
・そもそも GetPointer() というメソッドの必要性 が謎です.
 加えて,その戻り値がわざわざvoid*というのが更なる謎です.
 このメソッドの意図がわかりません.
・135行目は 129行目でcharactor[0]に入れた値を上書きしてしまうので,いろいろと問題ありですよね.
すみません、これは一応はテストのつもりで、実用する時は用途が変わります
当たり判定を使用する際に、二つのアドレスを、当たり判定をするクラスへ渡せないだろうかと考え、その際どうしたら渡せるか?
また、どのような振る舞いをするか?
をとりあえず自分で確認しようと思い作ったコードになります
上書きした理由はちゃんとEnemyとしての機能を保持しているか確認するためにわざと上書きしました

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: C++におけるポインタの質問

#7

投稿記事 by softya(ソフト屋) » 10年前

Spika さんが書きました:名前を固定するため、ここへ登録したのですが、パスを忘れたのか間違えていたのかはいれなくなり、メアドも一部逆にしてしまっているようで、名前を変えざる得なくなってしましました。
前の名前はBoneです。
ご本人に間違いない事は確認できました。
必要であればメールアドレス等を変更できます。
パスワードも一時的なものに変更可能です。※ 元のパスワードは管理人にも分かりません。
削除もできますが、すぐに同じ名前で登録できるか未確認です。たぶん、出来ると思いますが。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

アバター
h2so5
副管理人
記事: 2212
登録日時: 13年前
住所: 東京
連絡を取る:

Re: C++におけるポインタの質問

#8

投稿記事 by h2so5 » 10年前

PlayerとEnemyはCharactorクラスを継承しているんですよね。
それなら、当たり判定クラスのメソッドではCharactor*で受け取ればいいと思います。
void*を経由する必要はありません。

あと、CharactorではなくCharacterですよ。

Spika

Re: C++におけるポインタの質問

#9

投稿記事 by Spika » 10年前

softya(ソフト屋) さんが書きました:
Spika さんが書きました:名前を固定するため、ここへ登録したのですが、パスを忘れたのか間違えていたのかはいれなくなり、メアドも一部逆にしてしまっているようで、名前を変えざる得なくなってしましました。
前の名前はBoneです。
ご本人に間違いない事は確認できました。
必要であればメールアドレス等を変更できます。
パスワードも一時的なものに変更可能です。※ 元のパスワードは管理人にも分かりません。
削除もできますが、すぐに同じ名前で登録できるか未確認です。たぶん、出来ると思いますが。
ありがとうございます!
御手数かけて申し訳わけありません
間違っている部分というのが
gmailがgmialとなって決まっている部分です。
もし、御手数でないのならよろしくお願いします!

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: C++におけるポインタの質問

#10

投稿記事 by softya(ソフト屋) » 10年前

確かにメールアドレスが間違ってますね。直してみましたのでお試しください。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

Spika

Re: C++におけるポインタの質問

#11

投稿記事 by Spika » 10年前

h2so5 さんが書きました:PlayerとEnemyはCharactorクラスを継承しているんですよね。
それなら、当たり判定クラスのメソッドではCharactor*で受け取ればいいと思います。
void*を経由する必要はありません。

あと、CharactorではなくCharacterですよ。
はい、継承しています!

コード:

#pragma once
#include <iostream>
typedef struct Point{
	int x;
	int y;
}t_pos;

typedef int GRAVITY;

class Object_Task{
public:
	virtual void Initialize() = 0;
	virtual void Update() = 0;
	virtual void Draw() = 0;
	virtual void Finalize() = 0;
};

class Object_Base:public Object_Task{
protected:
	t_pos pos;
	GRAVITY g;
public:
	virtual int GetPointX() = 0;
	virtual int GetPointY() = 0;
	virtual t_pos GetPoint() = 0;
	virtual void Initialize() override;
	virtual void Update() override;
	virtual void Draw() override;
	virtual void Finalize() override;
};

class Character:public Object_Base{
	int hp;
public:
	Character(int x,int y);
	Character(){}
	virtual void* GetPointer();
	virtual int GetPointX() override;
	virtual int GetPointY() override;
	virtual t_pos GetPoint() override;
	virtual void Initialize() override;
	virtual void Update() override;
	virtual void Draw() override;
	virtual void Finalize() override;
	void PrintData(int);
};
class Player:public Character{
public:
	Player(int x,int y);
	virtual int GetPointX() override;
	virtual int GetPointY() override;
	virtual t_pos GetPoint() override;
	virtual void Initialize() override;
	virtual void Update() override;
	virtual void Draw() override;
	virtual void Finalize() override;
};
class Enemy:public Character{
public:
	Enemy(int x,int y);
	virtual void* GetPointer() override;
	virtual int GetPointX() override;
	virtual int GetPointY() override;
	virtual t_pos GetPoint() override;
	virtual void Initialize() override;
	virtual void Update() override;
	virtual void Draw() override;
	virtual void Finalize() override;
};
このような継承を行っています。
またつづりを・・・
訂正ありがとうございます!

Spika

Re: C++におけるポインタの質問

#12

投稿記事 by Spika » 10年前

いまひとつわからないのがthisポインタといいましたが、その理由として、
新ゲームプログラミングの館のC++におけるメニュー画面の作り方に書かれている

コード:

(BaseScene*) new Menu(this);
という時のアドレスはどこを示してるのかということがわからず、なおかつ、thisポインタについて調べても、自身のポインタといった書き方をしていて、今回もこうあるのでは?という勘で使っています。

Spika

Re: C++におけるポインタの質問

#13

投稿記事 by Spika » 10年前

softya(ソフト屋) さんが書きました:確かにメールアドレスが間違ってますね。直してみましたのでお試しください。
ありがとうございます。
お手数かけて申し訳有りません。
今から、やってまいります

アバター
h2so5
副管理人
記事: 2212
登録日時: 13年前
住所: 東京
連絡を取る:

Re: C++におけるポインタの質問

#14

投稿記事 by h2so5 » 10年前

Spika さんが書きました:いまひとつわからないのがthisポインタといいましたが、その理由として、
新ゲームプログラミングの館のC++におけるメニュー画面の作り方に書かれている

コード:

(BaseScene*) new Menu(this);
という時のアドレスはどこを示してるのかということがわからず、なおかつ、thisポインタについて調べても、自身のポインタといった書き方をしていて、今回もこうあるのでは?という勘で使っています。
この場合のthisはSceneMgrのインスタンスです。

アバター
usao
記事: 1889
登録日時: 11年前

Re: C++におけるポインタの質問

#15

投稿記事 by usao » 10年前

オフトピック
>それなら、当たり判定クラスのメソッドではCharactor*で受け取ればいいと思います。

仮に Player vs Enemy, Player vs Player, Enemy vs Enemy, ... という組み合わせによって
全く判定方法が異なるという話だとしたら,この中はどういう感じにするのがよいのだろう?
なんかこんな↓面倒そうな方法しか思い浮かばないのだけれど… うーん.
► スポイラーを表示

Spika

Re: C++におけるポインタの質問

#16

投稿記事 by Spika » 10年前

h2so5 さんが書きました:
Spika さんが書きました:いまひとつわからないのがthisポインタといいましたが、その理由として、
新ゲームプログラミングの館のC++におけるメニュー画面の作り方に書かれている

コード:

(BaseScene*) new Menu(this);
という時のアドレスはどこを示してるのかということがわからず、なおかつ、thisポインタについて調べても、自身のポインタといった書き方をしていて、今回もこうあるのでは?という勘で使っています。
この場合のthisはSceneMgrのインスタンスです。
ということは、実際通った実行場所のポインタということでしょうか?
SceneMgrのコンストラクタで行われたので、SceneMgrのインスタンスのアドレスが渡ったということでしょうか??

アバター
h2so5
副管理人
記事: 2212
登録日時: 13年前
住所: 東京
連絡を取る:

Re: C++におけるポインタの質問

#17

投稿記事 by h2so5 » 10年前

Spika さんが書きました: ということは、実際通った実行場所のポインタということでしょうか?
SceneMgrのコンストラクタで行われたので、SceneMgrのインスタンスのアドレスが渡ったということでしょうか??
SceneMgrのメソッド内に書かれているthisは必ずSceneMgrのインスタンスのポインタですよ。

>> usaoさん
Visitorパターンに近いですね。

Spika

Re: C++におけるポインタの質問

#18

投稿記事 by Spika » 10年前

h2so5 さんが書きました:
Spika さんが書きました: ということは、実際通った実行場所のポインタということでしょうか?
SceneMgrのコンストラクタで行われたので、SceneMgrのインスタンスのアドレスが渡ったということでしょうか??
SceneMgrのメソッド内に書かれているthisは必ずSceneMgrのインスタンスのポインタですよ。

>> usaoさん
Visitorパターンに近いですね。
ありがとうございます!
ようやくしこりがとれたようなきがします!

Spika

Re: C++におけるポインタの質問

#19

投稿記事 by Spika » 10年前

usao さんが書きました:
オフトピック
>それなら、当たり判定クラスのメソッドではCharactor*で受け取ればいいと思います。

仮に Player vs Enemy, Player vs Player, Enemy vs Enemy, ... という組み合わせによって
全く判定方法が異なるという話だとしたら,この中はどういう感じにするのがよいのだろう?
なんかこんな↓面倒そうな方法しか思い浮かばないのだけれど… うーん.
► スポイラーを表示
まだまだ、初心者なので、読み解くのに時間がかかりそうですが、コード例、出していただきありがとうございます!

Spika

Re: C++におけるポインタの質問

#20

投稿記事 by Spika » 10年前

softyaさんに質問です、一応、再発行してみたのですがメールは大体どれくらいで届くのでしょうか?

Spika

Re: C++におけるポインタの質問

#21

投稿記事 by Spika » 10年前

一応、当たり判定は長方形と円or長方形と正方形で、アクションです
大きさが異なるため、アドレスをよびそこから、画像サイズなどから判定を作ろうという策略です

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: C++におけるポインタの質問

#22

投稿記事 by softya(ソフト屋) » 10年前

Spika さんが書きました:softyaさんに質問です、一応、再発行してみたのですがメールは大体どれくらいで届くのでしょうか?
すぐに届きませんか?
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

アバター
usao
記事: 1889
登録日時: 11年前

Re: C++におけるポインタの質問

#23

投稿記事 by usao » 10年前

thisって何ですか? というのは,一旦structで考えてみるとわかりやすいかもしれません.

コード:

struct Cat
{
  int m_CP;  //猫力
};

void InitializeCat( Cat *this, int CP )
{  this->m_CP = CP; }

void Damage( Cat *this, int damage )
{  this->m_CP -= damage;  }

//
int main()
{
  Cat A,B;
  InitializeCat( &A, 10 );
  InitializeCat( &B, 5 );
  Damage( &B, 5 );  //かわいそうに…
}
Cat型のインスタンスを操作するための関数には,操作対象インスタンスのポインタを渡しています.
(この例では,InitializeCat()が2回呼ばれていますが,その引数thisの値は,1回目と2回目では異なります.)
これをクラスで書いたら

コード:

class Cat
{
public:
  Cat( int CP ){  this->m_CP = CP;  }
  void Damage( int damage ){  this->m_CP -= damage;  }
private:
  int m_CP;
};

//
int main()
{
  Cat A(10);
  Cat B(5);
  B.Damage( 5 );
}
のような感じになると捉え,両者の対応を見れば,thisって何をさしてるの?というが把握できるのではないでしょうか.
(クラス側のコードでも,コンストラクタ Cat::Cat() が2回呼ばれます.そのときのthisとは何か?)

オフトピック
>Visitorパターンに近いですね。
もうちょっと楽な方法(?)は無いものでしょうか.

Spika

Re: C++におけるポインタの質問

#24

投稿記事 by Spika » 10年前

softya(ソフト屋) さんが書きました:
Spika さんが書きました:softyaさんに質問です、一応、再発行してみたのですがメールは大体どれくらいで届くのでしょうか?
すぐに届きませんか?
届いてません・・・

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: C++におけるポインタの質問

#25

投稿記事 by softya(ソフト屋) » 10年前

Spika さんが書きました:
softya(ソフト屋) さんが書きました:
Spika さんが書きました:softyaさんに質問です、一応、再発行してみたのですがメールは大体どれくらいで届くのでしょうか?
すぐに届きませんか?
届いてません・・・
もしかして、迷惑メールに振り分けられていませんか?
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

Spika

Re: C++におけるポインタの質問

#26

投稿記事 by Spika » 10年前

[quote="usao" id=3,15065,119819]thisって何ですか? というのは,一旦structで考えてみるとわかりやすいかもしれません.

コード:

struct Cat
{
  int m_CP;  //猫力
};

void InitializeCat( Cat *this, int CP )
{  this->m_CP = CP; }

void Damage( Cat *this, int damage )
{  this->m_CP -= damage;  }

//
int main()
{
  Cat A,B;
  InitializeCat( &A, 10 );
  InitializeCat( &B, 5 );
  Damage( &B, 5 );  //かわいそうに…
}
Cat型のインスタンスを操作するための関数には,操作対象インスタンスのポインタを渡しています.
(この例では,InitializeCat()が2回呼ばれていますが,その引数thisの値は,1回目と2回目では異なります.)
これをクラスで書いたら

コード:

class Cat
{
public:
  Cat( int CP ){  this->m_CP = CP;  }
  void Damage( int damage ){  this->m_CP -= damage;  }
private:
  int m_CP;
};

//
int main()
{
  Cat A(10);
  Cat B(5);
  B.Damage( 5 );
}
のような感じになると捉え,両者の対応を見れば,thisって何をさしてるの?というが把握できるのではないでしょうか.
(クラス側のコードでも,コンストラクタ Cat::Cat() が2回呼ばれます.そのときのthisとは何か?)

完璧!とまでは、言えませんが、概念的にはわかりました!
このクラスのm_CpにCpを代入するという感じですかね?

アバター
usao
記事: 1889
登録日時: 11年前

Re: C++におけるポインタの質問

#27

投稿記事 by usao » 10年前

>このクラスのm_CpにCpを代入するという感じですかね?

この「インスタンスの」ですかね.
「structのコード側では引数で渡しているthisを,クラスのメソッドでは省略できる」
くらいに捉えるとよいです.
(暗黙的にthisという引数が追加で存在していて,自動で渡されてる,という感じ)

Bone
記事: 7
登録日時: 10年前

Re: C++におけるポインタの質問

#28

投稿記事 by Bone » 10年前

Spika さんが書きました: もしかして、迷惑メールに振り分けられていませんか?
振り分けられてました。
お騒がせしてすみませんでした!

Bone
記事: 7
登録日時: 10年前

Re: C++におけるポインタの質問

#29

投稿記事 by Bone » 10年前

usao さんが書きました:>このクラスのm_CpにCpを代入するという感じですかね?

この「インスタンスの」ですかね.
「structのコード側では引数で渡しているthisを,クラスのメソッドでは省略できる」
くらいに捉えるとよいです.
(暗黙的にthisという引数が追加で存在していて,自動で渡されてる,という感じ)
なるほど良くわかりました!
詳しい解説ありがとうございました!

閉鎖

“C言語何でも質問掲示板” へ戻る