• ベストアンサー
※ ChatGPTを利用し、要約された質問です(原文:継承を重ねた場合のコストはどうなるのでしょうか?)

継承を重ねた場合のコストは?

このQ&Aのポイント
  • 継承を重ねた場合のコストについて考えます。
  • 仮想関数のオーバーライド回数や継承回数によってコストが変わる可能性があります。
  • コンストラクタやデストラクタのインライン化の有無もコストに影響を与えます。

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

  • ベストアンサー
  • sha-girl
  • ベストアンサー率52% (430/816)
回答No.4

既に指摘のあるとおり、コンパイラに依存する部分なので 基本的にVisual Studio2005でどうだったかという話をします。 まず当たり前ですが、継承を重ねればコードサイズは増えます。ただし潤沢にメモリーがあるWindows環境では気になる問題ではありません。 また継承の階層を増やしていくと new/deleteが多発(秒間10万回等)する場合にコンストラクタ/デストラクタの呼び出しコストが顕著に現れます。 ただ生成(new)の回数を減らし、一度作成したオブジェクトは破棄せず使いまわす事で回避できます。 メモリーには常駐しますが速度的には良いです。 >全ての仮想関数は、オーバーライド回数は親・子・孫間で必ず1回に限定されるようにプログラムする場合 1回だろうが2回継承だろうが、呼び出しのパフォーマンスはほとんど変わらないと思います。 vtable(仮想関数テーブル) http://ja.wikipedia.org/wiki/%E4%BB%AE%E6%83%B3%E9%96%A2%E6%95%B0%E3%83%86%E3%83%BC%E3%83%96%E3%83%AB 等を調べてみてください。 >2. 仮想関数で最も恐れるべきはキャッシュミスだと思うのですが、 これは、プラットフォーム、特にCPUの分岐予測の性能に依存します。 経験的に昨今のWindows機ではほとんど影響ありませんが 階層に関係なくオーバーライドするだけでキャッシュヒットしなくなりパフォーマンスに影響を与えるゲーム機等はあります。 その場合に速度を重視するならクラスで継承とvirtualを使わないようにする・・・という前世代的な方法しかありません。 >3...インライン宣言されていない場合と、最終的にコストは等価になると考えてもいいのでしょうか? vtableを持つクラスのコンストラクタは一般的にインライン化出来ないと思います。 インライン宣言をすると、警告を出すコンパイラが多いかと思います。

LongSecret
質問者

お礼

おお! まさにこれっ、て感じの情報を色々とどうもありがとうございます。 >メモリーには常駐しますが速度的には良いです。 そうですね。普通の継承なしクラスでさえ、最適化で一時オブジェクトの生成が完全に消されない、かもしれない、と思うと、頻繁に呼び出されるところではむやみに確保するかもしれない表記すら避けたいときはあるくらいなので ましてや階層の大きな継承をしたクラスは、確保・解放はなるべく少なく抑えることを心がけています。(それでも、例えばMIDIファイルから読み込みしたときにイベント制御するとなると、仮想関数使いたくもなりますし、数千程度~万単位は普通に出現してもおかしくはないですがw 一回やればしばらく必要はないのでそれも問題はないでしょう。) >1回だろうが2回継承だろうが、呼び出しのパフォーマンスはほとんど変わらないと思います。 やはりそうですよね。 wikipediaはちら見はしていましたが、精読はしていませんでした。時間ができたらじっくり見てみようと思います。 >経験的に昨今のWindows機ではほとんど影響ありませんが >階層に関係なくオーバーライドするだけでキャッシュヒットしなくなりパフォーマンスに影響を与えるゲーム機等はあります。 こういう情報は今後の役に立つ可能性が高いので非常にありがたいです。 >その場合に速度を重視するならクラスで継承とvirtualを使わないようにする・・・という前世代的な方法しかありません。 どの道ユーザーが任意のファイル入出力を行えることを想定する場合は、ファイルからロードして最初に確保するときは、何らかの定数をenumやconst整数配列かなにかなどで持っておいて場合分けするしかないと思うので その時の定数を下のコードのようにクラスのIDとしてconstな整数メンバに埋め込んでおけば おんなじようにするなら、基底クラスにstaticメンバでも持たせてそこでswitch文を使うという方法を、別の仮想関数のかわりに用いる、ということになるでしょう。 それのチェックがいちいち煩わしいから純粋仮想関数を使いたくなってしまいますが。 しかし、仮想関数ははっきりと呼び出す先が分かってない限りインライン化出来ないので Windowsとかでも、よほど速度にこだわりたい場合にかぎっては、その手を使うこともあります。 私の場合は #define change_toaddsub というのをプリコンパイル済みヘッダーに定義してあるので、そういう場合は「static関数として親クラスにまとめて持たせる」というのを基本方針としてとりつつ クラスの宣言部に static 型 関数名(); ↓ change_toaddsub static 型 関数名(); などと書き加えておくことで、後でサブクラスを追加するときに手直しすべき関数をチェックするのを楽にしたりしています。 >vtableを持つクラスのコンストラクタは一般的にインライン化出来ないと思います。 コンストラクタ自体は呼び出す先が決まってるから、いつでもインライン化は出来るんじゃないかな?という風におもっていたんですが その状況ではそれ自体が誤りだったのですね! 確かに、いくらかパターンを用意してアセンブリコードを出力させてみたら、その全てがインライン指定の有無では 変わっていませんでした。 ものすごく簡単な、仮想ではない関数でもコンパイルオプションの最適化の設定であっさり変わりましたが、こちらは最適化の有無で変わらず、また __forceinline を付けても全然変わりませんでした。 >インライン宣言をすると、警告を出すコンパイラが多いかと思います。 そういうことであれば、やはり多少のコストについては割り切って使う、ということですね。逆に、そうだと分かっていれば、今まで書いてきた基底クラスのコンストラクタの中身によっては、余計なヘッダのインクルード減らせて、コンパイル時間を若干節約できるかもしれません。

全文を見る
すると、全ての回答が全文表示されます。

その他の回答 (3)

  • jacta
  • ベストアンサー率26% (845/3158)
回答No.3

「コスト」といっても、時間的なコストもあればサイズ的なコストもあります。 いずれにせよ、具体的な利用状況や処理系によります。 具体的なコードを示したうえで、想定している処理系(複数でも構いません)を明らかにしてください。

LongSecret
質問者

お礼

確かにそうですね。 ありがとうございます♪ 今回私が知りたいのは、時間的なコストです。 処理系は、ひとまず 開発環境ではVC++の2008または2010で OSとしてはWindowsのXP以降、32bit版または64bit版になります。 もちろん、質問の内容が それ以外にも当てはまりそうな事だった場合はそれらを含んで構いません。

LongSecret
質問者

補足

↓のコードだと、現状文字数などの関係でBBBに全く存在意義がないですが、もちろん実際には意味があるからこそ二段階に継承させたいので …疑問は、下の場合だと、BBBがなくてCCCやDDDがAAAから直に継承されている場合と、BBBを一度継承してさらにそれを継承しているかどうかによって、コンストラクタ・デストラクタ・仮想関数のコストは、それほどかわりがないと見て良いかどうか、というものです。

全文を見る
すると、全ての回答が全文表示されます。
  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.2

文章だけで書かれてもよくわからんので, 「こんな感じ」 というコードを出してほしいかなぁ.... 「2段に継承」というのがよくわからん.

LongSecret
質問者

お礼

CCC::CCC( int* ab, byte** data ) : BBB( CCC_CLASS_, ab[0], ab[1] ) { memcpy( &textlen, *data, sizeof textlen ); *data += sizeof textlen; text = (TCHAR*)malloc( (textlen+1) * sizeof(TCHAR) ); memcpy( text, *data, textlen*sizeof(TCHAR) ); *data += textlen*sizeof(TCHAR); text[textlen]=_T('\0'); } class DDD : private BBB { friend class AAA; float x, y, z; DDD( int*, byte** ); ~DDD(){} virtual void Func_V() const override { TCHAR c[200]; _stprintf_s( c, 200, _T("%d %d %d\r\n"), id, int1, int2 ); OutputDebugString( c ); _stprintf_s( c, 200, _T("%f %f %f"), x, y, z ); MessageBox( NULL, c , NULL, 0 ); } }; DDD::DDD( int* ab, byte** data ) : BBB( CCC_CLASS_, ab[0], ab[1] ) { memcpy( &x, *data, sizeof x ); *data += sizeof x; memcpy( &y, *data, sizeof y ); *data += sizeof y; memcpy( &z, *data, sizeof z ); *data += sizeof z; } AAA* AAA::New( byte** data ){ const byte id_ = **data; *data += 1; int ab[2]; memcpy( ab, *data, sizeof(ab) ); *data += sizeof(ab); switch ( id_ ){ case CCC_CLASS_ : return new CCC( ab, data ); case DDD_CLASS_ : return new DDD( ab, data ); } return NULL; } ロード・解放・確認用関数を作っていますが 一通りのチェックは↓これで出来るかと思います。 void AAA::Check(){ byte buf[1000]; byte* b = buf; int i=3; memcpy( b, &i, sizeof i ); b += sizeof i; for (int j=2;j--;){ *b = CCC_CLASS_; ++b; memcpy( b, &i, sizeof i ); b += sizeof i; memcpy( b, &j, sizeof j ); b += sizeof j; LPCTSTR c = _T("test"); WORD w = _tcslen(c); memcpy( b, &w, sizeof w ); b +=sizeof w; memcpy( b, c, w*sizeof(c[0]) ); b += w*sizeof(c[0]); } *b = DDD_CLASS_; ++b; memcpy( b, &i, sizeof i ); b +=sizeof i; memcpy( b, &i, sizeof i ); b +=sizeof i; float f_[] = { 0.1f, 2.0f, 30 }; memcpy( b, f_, sizeof f_ ); b = buf; Load( &b ); while(i--) Func_S( i ); Cleanup(); } 真ん中のクラスはこのコードだとBBBの一つしかありませんが、当然実際にはそれにあたるものがもうひとつ存在することになりますし、実際には遥かに長いので…概要としては、コードで示すと、こういう感じの構造のイメージです。 おー、ぎりぎり文字数大丈夫でしたw(残り1) というわけで、アドバイスありがとうございます♪

LongSecret
質問者

補足

意味を持たせず最小限のコードだと、この場合だめかもしれないのですが 2000文字の制限があるので、補足とお礼欄にまたがって書いてみます。 それでもかなり省略したり、エラーチェックを省いたり、等々しますが、実際のヘッダとソースの分類はインライン化の提案をしてるかどうかで判断してください。ただ、一つのソースファイルにそのままコピペして使えると思います。 AAAが親、BBBが子、CCCとDDDが孫で、CCCとDDDのみ実体を作れます。 それの管理はAAAがまとめて行うことを考えています。 #include <windows.h> #include <stdio.h> #include <tchar.h> #pragma comment ( lib, "winmm.lib" ) #pragma comment ( lib, "user32.lib" ) #pragma comment ( lib, "Gdi32.lib" ) class AAA { static AAA* first; static int deletetimes; //デストラクタが呼ばれた回数を確認用 static AAA* New( byte** data ); protected: AAA* next; int int1, int2; const byte id; enum { CCC_CLASS_ = 0 , DDD_CLASS_ }; AAA( int id_, int a_, int b_ ) : next(NULL), id(id_), int1(a_), int2(b_) {} virtual ~AAA(){ ++deletetimes; } virtual void Func_V() const = 0; public: static void Load( byte** data ); static void Check(); static void Func_S( int index ){ AAA* aaa = first; while (index--){ if (!aaa) return; aaa = aaa->next; } if (aaa) aaa->Func_V(); } static void Cleanup(){ AAA* aaa = first, *aaa2; while ( aaa ){ aaa2 = aaa->next; delete aaa; aaa = aaa2; } first = NULL; TCHAR c[30]; _stprintf_s( c, 30, _T("%d"), deletetimes ); MessageBox( NULL , c, NULL, 0 ); } }; AAA* AAA::first(NULL); int AAA::deletetimes(0); void AAA::Load( byte** data ){ int count; memcpy( &count, *data, sizeof count ); *data+=sizeof count; first = New( data ); AAA* aaa = first; --count; for (int i=count; i--; ){ if (!aaa) return; aaa->next = New( data ); aaa = aaa->next; } } class BBB : protected AAA { protected: BBB( int id, int a_, int b_ ); virtual ~BBB(){} }; BBB::BBB( int id, int a_, int b_ ) : AAA( id, a_, b_ ) {} class CCC : private BBB { friend class AAA; TCHAR* text; WORD textlen; CCC( int*, byte** ); ~CCC(){ free(text); } virtual void Func_V() const override { TCHAR c[30]; _stprintf_s( c, 30, _T("%d %d %d"), id, int1, int2 ); MessageBox( NULL, text , c, 0 ); } };

全文を見る
すると、全ての回答が全文表示されます。
回答No.1

「どんな機械語が生成されるか」という問いに対しては「コンパイラの勝手」です。 言語仕様はこの問いに対して何の答えもくれません。 プロファイルするとか、実際に吐いた機械語を吟味する以外、判断するすべはありません。 と前置きしたうえで、「それほどまでにコストを気にするアプリケーションなのか」が気になります。

LongSecret
質問者

お礼

どうも、ありがとうございます♪ やはりそうですか… >「それほどまでにコストを気にするアプリケーションなのか」が気になります。 単純に、速度の差があまりに小さくて誤差に埋もれてしまうような話なら、利便性をとるため二段の継承もしたいし、純粋仮想関数も適切に使いたいけども 速度の差が気になるようならそうも言えない という事を思っていたのですが どんな機械語が生成されるか言語仕様からは判断できないとなれば 確かに、その角度でもっと具体的に深く追求した方が良いですね。 というわけで コンストラクタ・デストラクタについては、ファイルの読み込みやアプリケーション終了などの理由から、コンストラクタ・デストラクタがぶん回されてる最中に、他のスレッドがちょっかいを出したり、何か膨大な解析をする可能性は完全に撤廃できる状況にあります。 従って、この点についてはあまりに遅くなければ問題ないということになります。 二段階継承にした時に最も上にくる基底クラスは、『インスタンス変数』としては 3つの単純な整数と、自分自身の型のポインタ(next)をさすメンバの、たった4つのメンバ変数を持ち、コンストラクタ中では初期化リストでそれらを初期化することしかしません。 これが 仮に、相当、かなり多く見積もって10万回呼ばれたとして 例えば、多く普及している平均的なの性能のXP以降ぐらいで差が1秒以内に収まるなら、全く気にならないレベルです。 意図的に余分なことをするわけはないので、それだけの差でさすがにたった10万回で1秒なんて到底かからないと見ていいでしょうか? ちなみに今ある、そこそこのファイルを読み込んだらコンストラクタが呼ばれた回数3000弱でした。 デストラクタはnextのポインタを使用して一括解放などとからんできますが、結局『継承とかかわりのある』行動としては、単に表記上virtualで一段階だったのが二段階になる、という以外全く変化はありません。 これも10万で1秒以内なら余裕です。 それ以外の仮想関数の問題については 別スレッドから可能な限り速く呼ばれる瞬間が発生するタイミングがあります。 その時に同時にメインスレッドで、仮想関数とは無関係にすさまじく膨大な演算が行われる可能性も、あるにはあります。 ただし、それは全体からみれば稀なケースです。 また、なるべくその回数を減らすようにすることも考えられます。 これは、一段の継承と二段の継承における仮想関数呼び出しの時間差が、もし発生した場合は、そのオーバーヘッドが、30万回で1秒以内ぐらいならよしとしておきます。 そんなに変わるようなことはまずないと思っていい、ですかね?

全文を見る
すると、全ての回答が全文表示されます。

関連するQ&A

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

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

  • 【delphi】クラスの継承、互換性について

    //Base.pas TSituation = class(TObject) public  procedure Update;virtual;abstract;  procedure Reflect;virtual;abstract; end; //Title.pas TSceneTitle = class(TSituation) private  ・  ・  ・ public  constructor Create;  destructor Destroy;override;  procedure Update;override;  procedure Reflect;override; end; //main.pas(メインフォーム) unit main; interface uses  ・・・, Base, Title;    ・    ・    ・ var  fm_main: Tfm_main;  Situation: TSituation; --------------------------------------------------- こう、きちんとクラスの宣言も継承もしているのに、(しているはず Situation := TSceneTitle.Create; とすると互換性がないといってコンパイルエラーになります。 なにかおかしいところがあるのでしょうか。

  • 【PHP】クラスを継承した際にデータ型も継承すると

    とある有料のオンライン学習サイトをつかっています。 学習項目の流れは以下の通りです。 現在「15 型の継承について見ていこう」で躓いています。 01 オブジェクトを使ってみよう (02:56) 02 投稿に関する処理を作ろう 03 クラスでデータ型を定義しよう 04 インスタンスを作ってみよう 05 コンストラクタを使ってみよう 06 クラスを整理しておこう 07 アクセス修飾子について見ていこう 08 メソッドを介してプロパティを操作しよう 09 プロパティで型宣言をしてみよう 10 staticキーワードを使ってみよう 11 オブジェクト定数を使ってみよう 12 クラスを継承してみよう 13 子クラスで独自の実装をしていこう 14 メソッドをoverrideしてみよう 15 型の継承について見ていこう *型の継承 *型を継承するメリット この項目で記述されているソースコードは下記のとおりです。コード内のクラス、SponsoredPostは クラスPostを継承しています。よって両方のクラスともにPost型として扱えると説明があります。 ソース内のこの箇所で processPostという関数を作成し、変数$postにPost型と型付けをしています そしてforeachでPostで型付けられた$post型(クラスPostとそれを継承したクラスSponsoredPost)をひとつづつ取り出し、processPostを用いてそれぞれにshow()メソッドで表示させています。 ----------------------- <?php class Post{ protected $text; public function __construct($text){ $this->text = $text; } public function show(){ printf('%s',$this->text); } class SponsoredPost extends Post{ private $sponsor; public function __construct($text, $sponsor){ parent::__construct($text); $this->sponsor = $sponsor; } public function show(){ printf('%s by %s', $this->text, $this->sponsor); } } $posts = []; $posts[0] = new Post('hello'); $posts[1] = new Post('hello again'); $posts[2] = new SponsoredPost('iPhone','Apple'); function processPost(Post $post){ $post->show(); } foreach($posts as $post){ processPost($post); ------------- クラスを継承すると親クラスのプロパティやメソッドが子クラスに継承されるというのは理解できています。「15 型の継承について見ていこう」という項目では 『Post型の変数を受け取る関数を作って、データ型が継承されることを説明していきます。』 と解説してあります。 クラスを継承すると親クラスのプロパティやメソッドが子クラスに継承されるというのは理解できています。私の知っているデータ型(文字列型、整数型、浮動小数点数型、論理型、配列型、オブジェクト型、リソース型、NULL)は下記の2か所だけです。 show()メソッド内の、['%s']と['%s by %s']で文字列が指定されています。 したがってこの項目で説明されている 『Post型の変数を受け取る関数を作って、データ型が継承されることを説明していきます。』 とは、「クラスを継承する際にプロパティやメソッドだけでなく、データ型、ここでは(['%s']と['%s by %s'])も継承されるということが説明されているという解釈でよろしいのでしょうか? 少し混乱しています。もし私の解釈が間違っているようでしたら教えてください。 初学者です。よろしくお願いいたします。 <表示結果>

    • ベストアンサー
    • PHP
  • コンストラクタの記述について ―引数を持ったクラスを継承する場合―

    コンストラクタの記述について ―引数を持ったクラスを継承する場合― ActionScript3.0でプログラミングをしています。 クラスの継承に挑戦したのですが、うまくいきません。 コンストラクタの記述は、何か特別なものが必要なのでしょうか? ■コンストラクタに引数なし → 成功。 ■コンストラクタに引数あり → 失敗。  エラー「No default constructor found in base class <親クラスの名前>」。 ■エラーの出るソース↓ ・Main.as(コンストラクタ内抜粋)     var parent:Parent = new Parent(100);     var child:Child = new Child(200); ・Parent.as package {   import flash.display.Sprite;      public class Parent extends Sprite {     protected var str:String = "親クラスのプロパティ";     public function Parent(inNum:Number):void {       trace("親クラス, ", str, inNum);     }   } } ・Child.as package {   import Parent;   public class Child extends Parent {     public function Child(inNum:Number):void { //■エラー。       trace("子クラス, ", str, inNum);     }   } } ご存知の方、よろしくお願いします。 よろしくお願いします!

    • ベストアンサー
    • Flash
  • 継承における暗黙のデフォルトコンストラクター

    ”継承の際、スーパークラスで引数なしのコンストラクターが省略せずにきちんと記述されるなら、そのサブクラスでコンストラクターを記述しなくても、スーパークラスの引数なしのコンストラクターが受け継がれるためコンパイルエラーがおきない。”のは分かりますが”スーパークラスで引数なしのコンストラクターが省略され、かつサブクラスでコンストラクターを省略した場合”はなぜコンパイルエラーがおきるのでしょうか? 暗黙の内にスーパークラスにコンストラクターが生成され、それがサブクラスに受け継がれることは出来ないのでしょうか? 宜しく願います。

  • C++の継承と呼び出しについて

    C++について COMとMediaFoundationについて勉強中ですが、継承とオーバーライド の部分で混乱してしまったので、アドバイスをお願いします。 IUnknownクラスは、三つの純粋仮想関数を持っていて、 virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject)=0; virtual ULONG STDMETHODCALLTYPE AddRef(void)=0; virtual ULONG STDMETHODCALLTYPE Release(void)=0; の三つがあることがわかりました。 そのIUnknownクラスを継承したIMFAsyncCallback、 IMFAsyncCallbackをさらに継承したCPlayerクラスがあります。 CPlayerクラスの中でCPlayer::QueryInterfaceの定義・処理が記述されています。 ここで、ほかのCPlayerクラスの関数内で IUnknownのインスタンス->QueryInterface(引数) ; で呼び出された場合、 CPlayer::QueryInterfaceには飛ばないのでしょうか? 何度ブレークポイントを張ってもきていないので、 いったいどこで処理が行われているか不思議で仕方ないです。 というかIUnknownのインスタンスが作れていることすら疑問です。。。 よろしくお願いします。

  • ダイアログを継承したダイアログの作成について

    お世話になります。 今回お聞きしたいことは、 オリジナルに作成したダイアログを継承したオリジナルのダイアログを作成した際に、オリジナルに作成した基底ダイアログのダイアログ上のコントロールや、そのコントロールの位置を継承することはできますでしょうか? ということです。 何がしたいかといいますと、4つのダイアログをメインダイアログから呼び出すのですが、その4つのダイアログには共通するコントロールがあり、そのコントロールの動作もその位置も全く同じなのです。 そのため、いちいち4つのダイアログにコントロールの貼り付けや、処理を記入せずに、その共通のコントロールをもった基底ダイアログを作成して、その基底ダイアログの継承としてダイアログが作れたらなと思い、質問させて頂きました。 継承をすると、基底クラスの関数等を使うことができるというのはわかるのですが、ダイアログ上のコントロールの位置までは不可能なのかなと疑問に思いました。 ご回答を宜しくお願い致します。 開発環境は Windows CE 6.0 Visual Studio 2005 です。

  • 複数のクラスで共通した関数を使いたい場合

    C++なのですが、複数のクラスで共通して使いたい関数がある場合、親クラスに共通したい メンバ関数を作り、その子として複数のクラスを作るのが良いのでしょうか? それ以外の方法だとクラスの外でstatic宣言した関数であればクラス内で使えるようでした。 (static宣言しないとコンパイルエラーとなりました) しかし以下のサイトにあるように「共通関数継承のデメリット」があるようで推奨していないようです。 ttp://d.hatena.ne.jp/katzchang/20110216/p1 ttp://blog.jnito.com/entry/20110217/1297896355 なお、自分には上記サイトの内容は難しくて理解できませんでした。 つまり、「数のクラスで共通して使いたい関数がある」場合、上記サイトはどうすればいいと言っているのでしょうか? よろしくお願い致します。

  • 継承について

    下の質問の回答、間違ってませんか? -------------------------------------------- 親クラスのフィールドをメソッドを全て継承することになります。よって、サブクラス2は、サブクラス1とスーパークラスのメンバーを全て持つことになります。サブクラス2をインスタンス化すると、サブクラス1とスーパークラスが全てインスタンス化(コンピューターのメモリ上等に配置)されます。 ただ、可視性というものがあり、サブクラスから親クラスのメンバーを直接取り扱えない場合があります。privateや可視性修飾子無しの場合、サブクラスから直接取り扱えません。ただ、継承はされているので、インスタンスとしては存在します。例えば、 class スーパークラス{ private int abc; public int getAbc(){ return this.abc; } というクラスがあり、これを継承したサブクラスがあったとします。 サブクラスからは、privateなメンバー変数abcは直接取り扱うことができません。ただ、publicなgetAbcメソッドはサブクラスから取り扱えます。これで何が分かるかといいますと、privateなメンバーでもサブクラスに継承されるのです。単に可視性の問題で直接取り扱えないだけなのです。 また、オーバーライドされたメソッドがあったとしても、super.メソッド()で親のメソッドも呼べますので、これも継承されているのです。

  • 継承について

    みなさま、どうかお知恵を貸して下さい。 javaを勉強中で、本を読みながら試しに動かしています。 現在、実現したい動作が実現可能かどうかを調べているところです。 そのため、環境やバージョン等は決まっておりません。 むしろ、実現可能な環境やバージョンがあれば、教えてください。 実現したい機能ーーーーーーーーーーーー 親クラスAにメンバーとメソッドを定義します。 Aを継承する子クラスBを定義します。 プログラム中で、A、Bのインスタンスを生成します。 そして、A、Bを継承するCのインスタンスを生成したいのです。 Cのメンバーやメソッドは、Bと同様のものです。 この場合、BのクラスからCのようなインスタンスを作成することは、可能なのでしょうか? ・・・Cを定義していないので、おそらく不可能かと思います。 やはりこういった場合、Aを継承しているBを継承するCクラスを定義しておく必要があると考えています。 では、Cを継承するD,Dを継承するE・・・というように、いくつ必要になるかわからない場合、最大数分継承したクラスを用意すべきでしょうか。 なぜ、そうしたいかというと、組織図のようなものを作成したいのですが、組織図を構成する人数は、ユーザーの任意としたいのです。 継承したクラスを用いれば、そのまま組織図の体系を表現できる気がしました。 質問が大雑把になってしまい、申し訳ないのですが、お力を貸していただければ幸いです。

    • ベストアンサー
    • Java