アプリ版:「スタンプのみでお礼する」機能のリリースについて

仮想関数でのオーバーライドでの質問
二つの派生クラスを定義したのですが、一つ目のクラスのメソッドが実行されないで困っています。
下記にソースを載せておきます。
どこが原因でそうなるのかご指摘お願いします。

/*
継承
*/
#include <iostream>

using namespace std;

class Var
{
private:
int value;
static Var* re;

public:
// 静的関数
static bool func() {
// 内部で同一の関数を呼び出す
re->show();
return true;
}

virtual show() {
cout << "message00" << "moji" << endl;
}

// 自身のポインタを取得
Var() { re = this; }
};

Var* Var::re = NULL;

class Msg01 : public Var
{
private:
int value;

public:
show(void) {
cout << "message01" << "moji" << endl;
}
};

class Msg02 : public Var
{
private:
int value;

public:
show(void) {
cout << "message02" << "moji" << endl;
}
};

int main()
{
Msg01 val;
Msg02 msva;

val.func();
msva.func();

getchar();

return 0;
}

/------------------------------------------------------/
実行結果
message02moji
message02moji
/------------------------------------------------------/
message01mojiが表示されるはずなんですが表示されないでいます。
Msg02を宣言したためこのようになってしまったんでしょうか?

A 回答 (5件)

以下、No2の要求に対する簡単な例を挙げます。



#include <iostream>

using namespace std;

//****************************
//
//****************************
class Var
{
 private:

 public:
  virtual void func() {
   cout << "message00" << "moji" << endl;
  }

};

//****************************
//
//****************************
class Msg01 : public Var
{
 private:

 public:
  void func() {
   cout << "message01" << "moji" << endl;
  }
};

//****************************
//
//****************************
class Msg02 : public Var
{
 private:

 public:
  void func() {
   cout << "message02" << "moji" << endl;
  }
};

//****************************
//
//****************************
int main()
{
 Msg01 val;
 Msg02 msva;
 Var  *base[2];

 base[0] = &val;
 base[1] = &msva;

 base[0]->func();
 base[1]->func();

 getchar();

 return 0;
}
    • good
    • 0
この回答へのお礼

 回答ありがとうございます。
 配列として管理すればちゃんとできるんですね。
このやり方でWIndowsプロシージャの継承をやってみようと思います。

お礼日時:2010/01/21 16:19

関数を static で宣言すると「オブジェクトの情報」は完全に消えますから, static な関数から非static な関数を呼び出すためには消えてしまった「オブジェクトの情報」を static な関数に何らかの形で渡す必要があります. ですから, func を基底クラスに static にしたままで「val.func() から Msg01::show() を呼んでほしい」とか「msva.func() から Msg02::show() を呼んでほしい」というのは本質的にかなり無理があります. func に「実際のオブジェクト」を渡すくらいしかないんじゃないかなぁ.


ちなみに普通「Msg02 を宣言する」といったら class Msg02; だけだし, 拡大解釈しても class Msg02 : public Var { ... }; までだから, これ*だけ*で「Msg01::show を呼ばなくなる」ということはないです. Msg02 のコンストラクタを呼ばなければいい....
    • good
    • 0
この回答へのお礼

 早速の回答ありがとうございます。
ウィンドウプロシージャだと静的プロシージャから動的にもってかないと派生クラスを生かせないので
こういった質問をしました。
Taconsan氏の仰る通りだと、ウィンドウプロシージャをクラスに内包して使うのは危険なんでしょうかねぇ。

お礼日時:2010/01/21 22:48

Var::func を static にしない.

この回答への補足

 どうしても静的関数から呼び出したいのです。

補足日時:2010/01/21 16:12
    • good
    • 0
この回答へのお礼

 回答ありがとうございます。
実はWinAPIのプロシージャのクラス化をして継承可能にしようとしている最中なんです。
それでどうしても静的にしなければならないのでこういうプログラムを書いています。

お礼日時:2010/01/21 16:15

Var* Var::re = NULL;


がグローバル宣言になってるから一個しか存在しない。
Msg01 val;
を実行した時点では Var::re は val だけど
Msg02 msva;
を実行した時点で Var::re は msva に書き換えられてる。
なので val.func(); では msva->show( ) がコールされる。

この回答への補足

  このソースの実行結果が正常に
message01moji
message02moji
にするにはどうしたらいいんでしょうか?
ここでも対策できず詰んでしまっています。
 二重に質問してしまうのかも知れませんが、もしよろしければお願いします。

補足日時:2010/01/21 11:05
    • good
    • 0
この回答へのお礼

ご指摘ありがとうございます。
ずっとこれで煮詰まってたんで、回答が欲しかったです。

お礼日時:2010/01/21 10:53

「Msg02を宣言したため」が何を意味するのかよくわからんのだけど,


Msg02 msva;
で Var::Var() が実行されている.

この回答への補足

 「Msg02を宣言したため」というのは、Msg02を宣言したからMsg01のshow()が呼ばれなくなったのではないか?と考えていたからです。実際注釈して無効にしてたら実行結果が変わったんで。
なのでMsg02の宣言がMsg01に影響をもたらしていると考えていたのですが、何故かはわかりませんでした。

補足日時:2010/01/21 10:58
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!