• ベストアンサー

C++のデストラクタについて

クラスAの変数Xをクラス外から変更した際に、クラスAのデストラクタに行くのですが、それは正しい処理なのでしょうか? 変数の変更はDXUTSetCallbackKeyboardでキーを押したときに変更されるようになっています。

noname#142252
noname#142252

質問者が選んだベストアンサー

  • ベストアンサー
回答No.5

>クラス外から変数の値を変える方法は他にないでしょうか? 普通にやるならば、2通りあります。 ■AnimationFlag を公開する  AnimationFlag 変数の型の前に public: をつけるだけです。  ただし、お勧めしません。クラスの価値が半減します。 ■AnimationFlag を変更するメソッドを追加する  AnimationFlag は private: なので外部からアクセスできませんが、  AnimationFlag を変更するメソッドを追加して公開することで、  間接的に変更します。 class CTiny { private:   bool AnimationFlag;   ~他の変数~ public:   void SetAnimationFlag(bool b){ AnimationFlag = b; }   ~他のメソッド~ };  通常はこのように間接的にアクセスさせます。  クラス外からアクセスするときは、SetAnimationFlag を呼んでやります。

noname#142252
質問者

お礼

こんな方法があるのは思いつきませんでした。 参考にしたいと思います

その他の回答 (4)

回答No.4

 補足頂きました。スタティックメンバ変数にしたら、実態をソースの中に書かないといけません。  ソースの中(何処か1箇所に)  char CTiny::AnimationFlag = 0;//初期化するのはココで行う  と書かないといけません。 >>キーを押すとFlagの値が変わるつもりなのですが、動作を見る限り全く値が変更されていません。 >>CTinyクラスのパブリックでAnimationFlagをcharを使って初期化した後、コンストラクタで値を代入しています。  スタティックメンバ変数は、コンストラクタで初期化はしない方が賢明です。  値が変更されないのはスタティックメンバ変数をコンストラクタで初期化しているからです。   void CALLBACK KeyboardProc( UINT nChar, bool bKeyDown, bool bAltDown, void* pUserContext ) { CTiny Tiny;//ココを通過する度にAnimationFlagの中に初期化数値が入ってしまう if( bKeyDown ) { switch( nChar ) { case 0x5A: Tiny.AnimationFlag = 0; break; case 0x58: Tiny.AnimationFlag = 1; break; case 0x43: Tiny.AnimationFlag = 2; } } }  CTinyのコンストラクタから、スタティックメンバ変数の初期化を消して、以下の様にする。 void CALLBACK KeyboardProc( UINT nChar, bool bKeyDown, bool bAltDown, void* pUserContext ) { if( bKeyDown ) { switch( nChar ) { case 0x5A: CTiny::AnimationFlag = 0; break; case 0x58: CTiny::AnimationFlag = 1; break; case 0x43: CTiny::AnimationFlag = 2; } } }

回答No.3

 こんにちは。  CTinyのクラスとしての動きは正しいです。  ・・・が、プログラムとして、正しいかどうかは分かりません。  Tiny.AnimationFlag がスタティックメンバ変数ならば、値は常に保持されますが、そうでないならば、変数に代入した意味が全く無いと言う事です。  で、Tiny.AnimationFlag がスタティックメンバ変数だった時、  CTiny Tiny;  Tiny.AnimationFlag = 0;  とするよりも、  CTiny::AnimationFlag = 0;  とした方が良いでしょう。  スタティックメンバ変数へアクセスする場合は、CTinyのインスタンスは必要有りません。  寧ろ、コンストラクタ、デストラクタの作動するコストが無駄と言う事になります。

noname#142252
質問者

補足

CTiny::AnimationFlag = 0;のように変えて、AnimationFlagをstaticに変えてみたら 「error LNK2001: 外部シンボル ""public: static char CTiny::AnimationFlag" (?AnimationFlag@CTiny@@2DA)" は未解決です。」 と出てしまいました。 自分にはまだよく分からないのですが、クラス外から変数の値を変える方法は他にないでしょうか? キーを押すとFlagの値が変わるつもりなのですが、動作を見る限り全く値が変更されていません。 CTinyクラスのパブリックでAnimationFlagをcharを使って初期化した後、コンストラクタで値を代入しています。

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.2

「↑の括弧まで来ると」のところで Tiny のライフタイムが切れるので, そこで Tiny に対し CTiny::~CTiny() を呼び出すのは仕様です.

  • min_is
  • ベストアンサー率25% (1/4)
回答No.1

ソースが無いので、想像ですが、クラスAのオブジェクトを関数の引数に 渡して、その関数内で変数Xを変更していませんか? その場合、引数を参照あるいはポインタで渡さないと関数から戻るときに クラスAのデストラクタが呼ばれます。

noname#142252
質問者

補足

変数を変えるキーイベント。変数XはAnimationFlag void CALLBACK KeyboardProc( UINT nChar, bool bKeyDown, bool bAltDown, void* pUserContext ) { CTiny Tiny; if( bKeyDown ) { switch( nChar ) { case 0x5A: Tiny.AnimationFlag = 0; break; case 0x58: Tiny.AnimationFlag = 1; break; case 0x43: Tiny.AnimationFlag = 2; } } } ↑の括弧まで来ると、CTinyのデストラクタへ飛んでしまう クラスAことCTiny void CTiny::SetIdleKey( bool bResetPosition ) { DWORD dwNewTrack = ( m_dwCurrentTrack == 0 ? 1 : 0 ); LPD3DXANIMATIONCONTROLLER pAC; LPD3DXANIMATIONSET pAS; m_pAI->GetAnimController( & pAC ); switch(AnimationFlag) { case 0: pAC->GetAnimationSet( m_dwAnimIdxLoiter, & pAS ); break; case 1: pAC->GetAnimationSet( m_dwAnimIdxWalk, & pAS ); break; case 2: pAC->GetAnimationSet( m_dwAnimIdxJog, & pAS ); }           ・           ・           ・ こんな感じです。m_dwAnimIdxJogはchar

関連するQ&A

  • C++ Vectorのデストラクタ

    C++ Vectorのデストラクタ boost::any型のVectorに自作クラスをpush_backで入れると、なぜかその自作クラスのデストラクタが呼ばれてしまって困っています。 またそのクラスの関数を実行すると同じようにデストラクタが呼ばれてしまいます。 

  • C++のクラスの仮想デストラクタについて

    C++のクラスの仮想デストラクタについて教えてください。 デストラクタは、クラスの名前の前にチルダを付けたものが名前になりますが、とあるクラスの継承クラスは、その親クラスとクラス名が違うので、デストラクタの名前も親クラスのものとは別になる。つまり。継承関係のあるクラスでもデストラクタはオーバーライドせず、各クラス毎に別の名前で存在する、ということになると思います。 ですので http://wisdom.sakura.ne.jp/programming/cpp/cpp31.html このページの下部にあるように、「デストラクタは、派生クラスから基本クラスへ向かって順番に呼び出される」というのもなんとなく合点が行きます。 しかし、仮想デストラクタというものがあることを知りました。 上記のようにデストラクタは継承関係のあるクラス間でも、それぞれクラス毎に作ればよいと思っていましたが、子クラスの方でオーバーライドする必要がある場合があるのでしょうか。あるとすれば、それはどんな場合なのでしょうか。 また、上記のURLでは、「C++ 言語のデストラクタはオーバーライドを行いません」と書いてあり、なんだかよく分からなくなってきました。仮想デストラクタというものが存在するのに? どなたか詳しい方いらっしゃいましたらご教示頂けると幸いです。

  • C++ CLI のデストラクタについて

    VisualStudioにてWindowsフォームアプリを作成する際、自動で以下コードが記載されています。 デストラクタ protected: ~Form1( ) { if (components) { delete components; } } private: System::ComponentModel::Container ^components; 変数componentsは、定義されてはいるのですが、componentsにAddされているものが無く、デストラクタに削除される為だけに存在している様に見えます。 このcomponentsは何の為に作成されているのでしょうか?

  • C#デストラクタが走る理由がわからない(初心者)

    WPF C# アプリを初めて組んでいます。 MainWindowクラスで、publicなクラス変数配列(myclass)を定義し、 MainWindowのコンストラクタ(もしくはLoadedイベント)で、上記クラス変数にインスタンスを生成しています。 そのインスタンスを、MainWindows内のコントロールイベント(Button_Click)で参照しようとするとNullとなっておりました。 MainWindowのコンストラクタ(もしくはLoadedイベント)完了後に、デストラクトが走っているようです。 どこからも参照されていなければGCが走りデストラクタされるのはわかるのですが、 この場合、MainWindowクラスのメンバにクラス変数を追加し、そこにインスタンスを生成しています。よって、MainWindow(つまりアプリが)が終了するまでインスタンスが参照されているため、 デストラクタが走らないのではないかと考えておりました。 ですが、上記の通り、MainWindowのコンストラクタ(もしくはLoadedイベント)後には、MyClassデストラクタが走ってしまいます。この辺を教えていただけないでしょうか。 また、下記のように、Clickでインスタンスを参照するにはどうすればよいでしょうか。 public partial class MainWindow : Window {     MYClass []myclass;     public MainWindow()     {         InitializeComponent();         //ファイル読み込み(記載省略)         for(i=0; i<ファイル読み込み数;i++)         {             myclass[i] = new myclass(ファイル読み込みデータ);         }     }     private void Button_Click(object sender, RoutedEventArgs e)     {         for(int i=0;i<myclass.Length;i++) ←ここに来る前にすでにMyClassのデストラクタが走っており、nullとなっている         {             data = myclass[i].data;         }     } }

  • コンストラクタ・デストラクタ

    プログラミング言語はC++ C++を触り始めたばかりの素人です。 コンストラクタとデストラクタについて質問です。 下記に参考にしているウェブページから簡潔にしてコードを書いてみました。 コンストラクタ、デストラクタの中はそれぞれに、○○が呼び出されましたと書いてあるだけでよく分からなかったので別のウェブページを見たら コンストラクタは Sample::Sample(){ n=0; } みたいな例があったのですが、このように変数に予め何かの値を代入しておくという事で合ってますか? デストラクタは理解できていません。 下記の例では、どのような処理を書けばいいのでしょうか? #include<iostream> using namespace std; class Sample { private: int n; public: void Show(); Sample(); ~Sample(); }; void Sample::Show() { cout << n << endl; } Sample::Sample() { // n=0; std::cout << "コンストラクタが呼び出されました" << std::endl; } Sample::~Sample() { // どんな処理? std::cout << "デストラクタが呼び出されました" << endl; } main() { Sample sample; sample.Show(); return 0; } 実行結果 コンストラクタが呼び出されました 1     ←コンストラクタ関数内の//を削除で0になることは確認 デストラクタが呼び出されました

  • [PHP] デストラクタについて教えて下さい

    あるPHPの入門書にデストラクタについての解説があります。 *デストラクタ 「コンストラクタとは反対に、オブジェクトが破棄されるタイミングで実行されるのがデストラクタです。名前は __destructに固定されている。 デストラクタには、クラスの中で使用したリソースを破棄するなど、主に終了するときの処理を記述するのが一般的です。」 とあります。 以下のような記述をしました。(person.php) <?php class Person{ public $lastName; public $firstName;  public function __construct($lastName, $firstName){ $this->firstName = $firstName; $this->lastName = $lastName; } public function show(){ print "<p>私の名前は {$this->lastName} {$this->firstName}です。</p>"; } public function __destruct(){ print "<p>インスタンスが破棄されました。<p>";  } } ?> 上の記述をインスタンス化する記述です。(instancne.php) <?php require_once('person.php'); $p = new Person('田中', '幸太郎'); $p->show(); ?> <表示結果> 私の名前は 田中 幸太郎です。 インスタンスが破棄されました。 となります。試しにもうひとつインスタンスを追加します。 <?php require_once('person.php'); $p = new Person('田中', '幸太郎'); $p->show(); $p1 = new Person('鈴木', '京子'); $p1->show(); ?> <表示結果> 私の名前は 田中 幸太郎です。 私の名前は 鈴木 京子です。 インスタンスが破棄されました。 インスタンスが破棄されました。 説明にある、 「オブジェクトが破棄されるタイミングで実行されるのがデストラクタです。」 「デストラクタには、クラスの中で使用したリソースを破棄するなど、主に終了するときの処理を記述するのが一般的です。」 これらの意味がわかりません。 コンストラクタの 「new 演算子によってインスタンス化されるタイミングで実行される」 「プロパティの初期化」 などの意味は理解できているつもりです。 デストラクタを使うと「オブジェクトが破棄される」、「クラスの中で使用したリソースを破棄する」と ありますが、『一度インスタンスを作るとクラス内のリソースが破棄されるのかな?』と思い ためしにもう一つインスタンスを作成しました。上記の通り問題なく使えています。 膨大な記述になると、クラス、この場合は 「class Person」」は再利用出来なくすると言った意味になるのでしょうか? 他の教材やネットで検索してみたりしたのですが、イメージがつかめません。 以下のPHP公式のサイトから考えてみると、クラス内で参照できるものがなければ、コールされるという風に解釈できるかもしれませんが、意味がわかりません。 デストラクタ(__destruct)はコンストラクタ(__construct)の反対というように記述されているものもありますが余計に意味が分かりません。 初学者にもわかるようにデストラクタについて教えてもらえないでしょうか? またどういうケースで利用するのかもよく分かりません。 そのあたりも併せて教えて下さい。 宜しくお願いいたいます。 (参考) デストラクタ __destruct(): void PHP には、C++ のような他のオブジェクト指向言語に似たデストラクタの概念があります。 デストラクタメソッドは、 特定のオブジェクトを参照するリファレンスがひとつもなくなったときにコールされます。 あるいは、スクリプトの終了時にも順不同でコールされます。 https://www.php.net/manual/ja/language.oop5.decon.php

    • ベストアンサー
    • PHP
  • C++ クラスについて

    クラスについて今勉強しています。 そこで質問なんですが クラスの中にクラスというのは実現可能なのでしょうか? クラスAの中にクラスBとクラスCが入っている状態で、 クラスAの中にある関数XでクラスBやCの関数を呼ぶような処理を目指しています。 またクラスAに宣言されている変数をクラスB,Cの中で変更したりできないでしょうか?

  • PHP5 オブジェクトのリファレンスとデストラクタ

    PHP5.0.4を使っています。 原因不明の現象に悩まされていましたが、再現する最小限のコードがわかりました。 class Foo { function __destruct() { } } $bar=&new Foo(); $bar=&new Foo(); というコードで、最初の$barへの代入ではちゃんとFooクラスのオブジェクトへのリファレンスが代入されますが、2回目の代入では結果として$barはNULLになってしまいます。 (1)リファレンスでなく値の代入にする (2)変数名を変える (3)2回目の代入の前に$barをunset()する (4)デストラクタの宣言を削除する のいずれかで2回目もFooオブジェクトが$barに代入されるのですが、(1)は実際はそこそこ大きいオブジェクトなのでコピーするのは無駄、(2)実際はループになっており2回目以降の変数名を変えるのは不可能 ということで、現在は(3)の対処をしています。 Q1.何故こういう現象が起こるのか Q2.デストラクタ宣言の有無で変わるのは何故か Q3.どういう対処が正しいのか 実際の処理は、こんな感じです。 foreach($aaa as $x) {  $bar=&new Foo($x);  if( $bar->test() ) $value[]=&$bar;  /*ここに else unset($bar); を入れるとOK */ }

    • ベストアンサー
    • PHP
  • C++の話です。

    C++の話です。 静的メンバ変数としてクラスを宣言した場合、デストラクタが呼ばれていないようなのですが、呼ぶ方法はありませんか? できれば「new」「delete」を使わずできると理想的です。 分かる方教えていただけると助かります。 以下、サンプルコードです。 「デストラクタが呼ばれました」と出力されない上、デバッガを使って試してみましたが、やはり呼ばれていないようです。 #include<iostream> class Test{   public:     ~Test(){       std::cout<<"デストラクタが呼ばれました"<<std::endl;     } }; class A{   private:     static Test T; }; int main(){   A a;   return 0; }

  • privateデストラクタを持つクラスの拡張

    C++でprivateなデストラクタを持つクラスを拡張してサブクラスを作る方法はありますか?