ページ 11

初歩的な質問ですが

Posted: 2009年2月25日(水) 20:39
by dic
#include <stdio.h>
#include <string.h>

class	Task
{
	char	str[80];
public:
	static	void	Run();
	void	push();
};

void	Task::push() { strcpy( str, "test" ); }
void	Task::Run() { printf( "Run - %s\n", str ); }

void	main()
{

}
上記のソースをコンパイルすると
error C2597: 'Task::str' : スタティック メンバ関数内の不正なデータ メンバへの参照です
とコンパイルエラーがでます
static 関数から Taskクラスのメンバ変数にアクセスするにはどうすればよいのでしょうか?
char str[80]; を public にしてもダメでした

使用コンパイラ VC++6,0 です

Re:初歩的な質問ですが

Posted: 2009年2月25日(水) 20:51
by SCI
静的メンバ関数は、オブジェクトを実体化しなくても実行できるので、実体が作られなければ存在しないメンバ変数にアクセスできません。
どうしてもアクセスしたい場合、メンバ関数のポインタを介する方法があります。

Re:初歩的な質問ですが

Posted: 2009年2月25日(水) 21:27
by dic
#include <stdio.h>
#include <string.h>

class	Task
{
	char	str[80];
	void	(Task::*func1)();
	void	(Task::*func2)();
	void	push();
	void	print();
public:
	static	void	Run();
	void	Init();
};

void	Task::push(){
	strcpy( str, "test" );
}
void	Task::print(){
	printf( "%s\n", str );
}
void	Task::Run() {
	func1(); // error C2064
	func2(); // error C2064
}
void	Task::Init(){
	func1 = &Task::push;
	func2 = &Task::print;
}

void	main()
{
	Task	*task = new Task;

	task->Init();
	task->Run();
	
	delete task;
}
上記のようにしましたがコンパイルエラー
error C2064: 関数ポインタとして評価されない式を使って、関数を呼び出そうとしました。
とでます
どのように関数ポインタを呼び出せばよいのでしょうか?

Re:初歩的な質問ですが

Posted: 2009年2月25日(水) 21:39
by Justy

>どのように関数ポインタを呼び出せばよいのでしょうか?

 Run関数が staticでなければ、
[color=#d0d0ff" face="monospace]
(this->*func1)();
(this->*func2)();
[/color]

でいいのですが、staticがついているので、どのインスタンスでそのメンバ関数を呼び出すのかを
決めないと……。

 つまり、Run関数から staticを外すか、Run関数の引数に Taskクラスのポインタが参照を
渡せばいいのではないか、と思います。

Re:初歩的な質問ですが

Posted: 2009年2月25日(水) 21:51
by SCI
dicさん
関数ポインタはなんか別の件と混同してました・・・
で、ちょっと実験してみたんですが、やはり、どこかで実体を作るより方法はないでしょう。

Re:初歩的な質問ですが

Posted: 2009年2月25日(水) 21:56
by dic
Justyさん回答ありがとうございます
そうなんですよ 他の方のソースを見ていてて気になったもので 改良もかねていじっていたのです
そこで私が本で学んでいない static メンバ関数が使われていたので
メンバ関数を static にする理由がしりたいのです

なので Justyさんのおっしゃるとおり static 修飾しをはずせばコンパイルが通るのですが
staticメンバ関数にすることにより発生する利点とは何でしょうか?

Re:初歩的な質問ですが

Posted: 2009年2月25日(水) 22:00
by dic
SCIさん回答ありがとうございます
やはりコンストラクタを利用されますか
私にとって処理の流れのトレースが多少複雑になるのでスマートに書きたいのですが

ちょっとスレ違いしましたが、staticメンバ関数にする理由が知りたいのです

Re:初歩的な質問ですが

Posted: 2009年2月25日(水) 22:14
by 御津凪
> staticメンバ関数にすることにより発生する利点

たとえば、クラスで共有するデータ(これも static メンバ変数)の初期化や、
クラスメンバ関数や変数に依存しないが、クラス内でのみ使用する関数などがあります。

下記はぱっと思いついて考えた使用例です。
class Resource {
public:
    Resource( int data ):mData(data){++sCount;}
    ~Resource( void ){--sCount;}

    int GetData( void )const{return mData;}
    void SetData( int data ){mData = data;}

    static int GetResouceCount( void ){return sCount;}
private:
    static int sCount;
    int mData;
};

int Resource::sCount = 0;
Resource クラスを精製するたびに sCount が増加し、開放するたびに sCount が減少します。
Resource::GetResouceCount 関数を呼ぶことで、現在の Resource インスタンスの数を返します。

そんな感じのものです。

Re:初歩的な質問ですが

Posted: 2009年2月25日(水) 22:22
by Justy

>staticメンバ関数にすることにより発生する利点とは何でしょうか

 インスタンスを生成することなく使えるので、
名前空間の代わりに使われたり、何かの理由でコンストラクタを
隠蔽したいときとか、自分自身の生成したりとか。

 ぱっと思いついた例をあげると、

[color=#d0d0ff" face="monospace]
// 日付クラス
class Date
{
int year_, month_, day_;
public:
Date(int year, int month, int day);
static Date Today(); // 今日の日付を返す

int Year() const;
int Month() const;
int Day() const;
};[/color]


とか。

Re:初歩的な質問ですが

Posted: 2009年2月26日(木) 06:26
by dic
>御津凪さん Justyさん 回答ありがとうございます
なるほど オブジェクトのカウンタに使ったり 名前空間に使ったりするんですね
後々にはちょっと応用が必要になってくるかもしれないですね

staticメンバ関数の仕組みを使って処理する必要は
今のところあまり感じられません
使われる人は使うのでしょうが

実体がなくても実行できるという点は初耳でした
ありがとうございました