• ベストアンサー

クラスの設計の問題

今C++でクラスの設計をしています。 どう設計すれば、いいか分からないので、しっている方に教えていただきたいですが。 class A{ private: int id; public: int getId(); void setId(); }; class B{ private: int id; public: int getId(); void setId(); } class C{ private: int id; public: int getId(); void setId(); } この三つのクラスが、共通な機能があります。また、実装も同じで、 継承を利用して、どう設計すれば、いいですか? よろしくお願いします。

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

  • ベストアンサー
  • MrBan
  • ベストアンサー率53% (331/615)
回答No.4

継承でなく委譲(#3の回答のようなやり方)を使うのは、一般に 「インタフェースと実装の分離」という方針によるものと推測します。 他言語では"interface"というものが明示的に存在したり、 多重継承に制限があったりするので良くある手ですが、 C++の場合は、実装の継承にprivateな継承を使う手もなくはないです。 > class A: classD ↑こういう形ですね。 この場合のポイントは、class A : public classDではなく、class A : (private) classDであること。 classDとして扱われない(classDはただの実装用の存在であって、 設計上、classDとして扱われることを想定していない/べきでない)ということですが。 (以下、蛇足) ちなみに、「できるだけclass」がもしstructのことをさしているなら(違ったら失礼)、 C++のstructはclassの一種でデフォルトがpublic:なものに過ぎず、 struct IInterface {   ↓こう読み替えても大差なし。 class IInterface { public: # 後、C++でスマートポインタを否定すると旨みが減りますね。 # 例外脆弱なコードになりがちですし…。

その他の回答 (3)

  • koko_u_u
  • ベストアンサー率18% (216/1139)
回答No.3

>class A: classD >class B: classD >class C: classD > > 以上の形にすることでしょうか? いいえ class A {  D d_; public:  ... }; な風にするということです。

ikutame
質問者

お礼

返事ありがとうございました。 指摘されていた形にする理由は?

回答No.2

 こんにちは。こんな感じでしょうか。参考程度に。 struct IInterface { virtual ~IInterface(){ } virtual int getId() = 0; virtual void setId(/*???*/) = 0; }; struct CInterface : public IInterface { protected: CInterface(int id_) : id(id_) { } virtual int getId(){ return this->id; } virtual void setId(/*???*/){ /*this->id = ???*/; } private: int id; }; struct A : public CInterface { static std::auto_ptr<IInterface> CreateInstance(int id){ return new A(id); } private: explicit A(int id_) : CInterface(id_) { } }; struct B : public CInterface { static std::auto_ptr<IInterface> CreateInstance(int id){ return new B(id); } private: explicit B(int id_) : CInterface(id_) { } }; struct C : public CInterface { static std::auto_ptr<IInterface> CreateInstance(int id){ return new C(id); } private: explicit C(int id_) : CInterface(id_) { } }; int main(void) { std::auto_ptr<IInterface> aptr[] = {A::CreateInstance(1), B::CreateInstance(2), C::CreateInstance(3)}; for(int i = 0; i < sizeof(aptr) / sizeof(aptr[0]); ++i) { cout << aptr[i]->getId() << endl; } return 0; }

ikutame
質問者

補足

返事していただいて、ありがとうございました。 追加したいですが、ちょっとスマートポインタを使いたくないです。 また、できるたけ、classで実装したいということです。 すみませんが、ありがとうございました。

  • koko_u_u
  • ベストアンサー率18% (216/1139)
回答No.1

実装を継承したい場合は C++ の文法で言う継承はせずに、 共通の実装クラスを個別のクラスでメンバ変数として保持するのが普通だと思います。

ikutame
質問者

お礼

ちょっと、くわしく教えていただけませんか? 例えば、class D を作る。 class D{ protected: int id; public: int getId(); void setId(); } class A: classD class B: classD class C: classD 以上の形にすることでしょうか? あるいは、もっといい設計がないしょうか?

関連するQ&A

  • クラス作成

    C#にてクラス作成をしております。その中で疑問に思った点を質問させていただきます。 画像を枠内に表示させるクラス 実装すべき変数:枠番号、パス、 映像を枠内に流すクラス 実装すべき変数:枠番号、パス、再生時間 Flashを枠内に流すクラス 実装すべき変数:枠番号、パス など色々なクラスがあってそれをまとめたクラスを作成中です。 上記のクラスを実装するにあたって、共通の変数はクラスにしてしまい それを継承しましょうと言う指示がありました。これはどういった使い方をするものなのでしょうか? class Class2 { public int no { get; set; } public string path { get; set; } } class Movie : Class2 {    public float time{get;set;} public void Play(int frameNo, string path, float playtime){} } class Picture: Class2 {    public void Show(int frameNo, string path){} } これをForm1.cs内で Class2 cls = new Class2(); cls.path = "C:\\test"; cls.no = 11; とかすれば MovieやPictureで使いまわしができると思いきや MovieやPictureをNewすれば初期化されてしまう為、何か根本的に 私の考えが間違ってると思います。 共通の変数を別のクラスにしておいて継承して使うというのはどういった使い方をするのでしょうか? よろしければ例で教えていただけないでしょうか

  • C++ クラスをメンバにもつクラスについて

    お世話になります。C++初心者でうまくコードが書けません(><) クラス1と2があり、クラス1のメンバにはクラス2があります。 メインでクラス1をインスタンス化してクラス2のfunc2を呼び出します。 func2ではクラス1のインスタンスから呼び出された場合にクラス1の m_int1を取得します。 Class Class1{ public:  int m_int1;  Class2 m_Class2; }; Class Class2{ public: void func2(); }; void Class2::func2(){  /*ここの記述方法が分かりません*/  /*C1から呼び出されたらC1のm_int1に100を入れる*/  /*以下間違え*/  class1 C2_1;/*別のclass1のオブジェクトなのでこれに入れてもダメっぽい*/  C2_1.m_int1 = 100; } void main(){  class1 C1;  C1.m_int1 = 10;  C1.m_class2.func(); } C1.m_class2.func()の中から呼び出したC1にアクセスする方法が 分かりません(TT)。実体がまだあるのだからアクセスする方法は あると思うのですが・・・ どなたかよろしくお願いします。

  • ibatis select複数件の受入方について

    SqlMap.xmlにて </select> <select id="getDept" resultClass="blog.Dept"> SELECT * FROM blog </select> Deptにて; public class Dept { private int id[]; public int[] getId() { return id; } public void setId(int[] id) { this.id = id; } blogArticle.javaにて public void load()throws Exception { SqlMapClient sqlMap = MyAppSqlConfig.getSqlMapInstance(); sqlMap.startTransaction(); Dept dept = (Dept)sqlMap.queryForObject("getDept"); sqlMap.commitTransaction(); } 以下のエラーが出てしまいました No type handler could be found to map the property 'id' to the column 'id'. One or both of the types, or the combination of types is not supported. . deptのところを private int id[]; public int[] getId() { return id; } public void setId(int[] id) { this.id = id; から private int id; public int getId() { return id; } public void setId(int id) { this.id = id; に変えるとエラーは無くなりますが・・・ しかしながら配列型のBeanでは受入はできないということでしょうか。うまい方法はないでしょうか。 ご教授の程よろしくお願い申し上げます。

  • クラス設計について

    C++で通信データのクラス設計をしております。 実際の通信手順ではなく、通信データそのもののクラスの作り方で悩んでおります。 256byteのデータの先頭に識別IDがあり、データを受け取ったらそのID用のデータ表示をするようなことをしたいのですが、どのようにクラスを作ればいいのかが分かりません。 今考えているのは、ベースクラスを作り、そのベースクラスを継承した各ID用の子クラスを作っているのですが、もっといいやり方、いい例などがあれば教えてください。 初めてのクラス設計で悩みまくっています。

  • インタフェイス実装と抽象クラス継承を同時に使うには??

    私はjava初心者です、今練習問題で困っています。 1つのクラスに抽象クラスとインターフェイスを 実装することはできるのでしょうか? 例えば abstract class Car { private String gas; public void getGas(int gas) { this.gas = gas; } public abstract void enjin(); } interface Flying extends Pet { void show(); } 上のインタフェイスと抽象クラスを同時に下のクラスに継承、実装しよう とすると、どんな風にかけば良いのでしょうか class Zoon { public Zoon() { super(); } public void enjin() { System.out.println("どどどどど"); } public void show() { System.out.println("いいくるまだ"); } }

    • ベストアンサー
    • Java
  • 継承したクラスを、継承元のクラス型の引数に渡すとどうなるのでしょうか?

    継承したクラスを、継承元のクラス型の引数に渡すとどうなるのでしょうか? 以下のようなケースで、 #include "stdio.h" using namespace std; // baseクラス class base { private:  int m_nII;  int m_nJJ;  int m_nKK; public:  base(int i,int j,int k){ m_nII=i; m_nJJ=j; m_nKK=k; }  int GetSum(){ return (m_nII+m_nJJ+m_nKK); } }; // base 継承クラス class hoge : public base { public:  hoge() : base(1,2,3){} }; void func(base* obj){ // baseクラスを引数に取る関数  printf("sum is %d\n", obj->GetSum()); } // main int main(){  hoge objHoge;  func((base*)&objHoge); // <-キャストして渡す  return 0; } として、一応、gccでコンパイルは通り、実行結果も期待通りだったのですが、 このやり方で問題は無いのでしょうか? (たとえば継承先のクラスが独自のメンバを持っていたりなどした場合、期待した結果にならないとか・・) よろしくお願いします。

  • C++を勉強し始めたばかりの初心者なのですが、クラスの継承に関して・・・

    Visual C++ 2008で、新しいwindowsフォームアプリケーションを作成したら、Form1.hの上の方に public ref class Form1 : public System::Windows::Forms::Form という行がありました。これは開発環境に実装されている System::Windows::Forms::Formクラスを継承し、Form1クラスを新たに作成しますという意味なのですよね? このとき、2つ目のpublicは、継承の仕方、この場合結果的にはSystem::Windows::Forms::Formクラスに含まれるメンバの、private以外がそのまま受け継がれる、という事になりますよね? それで、このref classというのは、ポインタみたいな意味でしょうか?refは書かないと別の継承方法になるのでしょうか? また、最初のpublicはどういう意味なのでしょう? もしかして、この2つについては、System::Windows::Forms::Formクラスを継承して新規フォームを作る場合の、定型みたいなものなのでしょうか?

  • オブジェクト指向で、インターフェースにないメソッドを呼ぶ

    こんにちは。質問させてください。 現在C++でプログラムを書いているのですが、以下のようなプログラムを書いたとします(これ例ですので、実際のプログラムとは異なります)。 // ポインターを抽象化 class PointerInterface { }; // 抽象化したクラスを継承して整数型のポインタを作る class IntPointer : public PointerInterface { private:   // int型のポインタ   int *p; public:   int* get()   {     return p;   } }; // 抽象化したクラスを継承して少数型のポインタを作る class FloatPointer : public PointerInterface { private:   float *p; public:   float* get()   {     return p;   } }; PointerInterface* CreateInterface( bool flag ) {   PointerInterface* result = 0;   if( flag )   {     result = new IntPointer;   }   else   {     result = new FloatPointer;   }   return result; } void setIntPointer( PointerInterface* ptr ) {   // ここでint型のポインターを取り出して操作したい } void main() {   PointerInterface* ptr = CreateInterface( true );   setPointer( ptr ); } インターフェースは同じなのに継承先に内含されている変数のタイプが違い、それを取得したい場合が出てくると思います。 こういう場合どのように実装すれば、より美しくコーディングすることができるでしょうか? /* 私は 1:PointerInterfaceにvoid*を戻すメソッドを宣言する 2:setIntPointerの中で無理やりキャストして子クラスのgetを無理やり呼び出す という2つの方法が思いついたのですが、なんだかどっちのコーディングもピンときません。 お知恵を貸してください! ※今回はtemplateを使うというのは、なしでお願いします。 */

  • フレンドクラスにできない

    mediatorクラスからCOuterクラスのメンバ変数にアクセスできるようにフレンドクラスにしたつもりなんですが、 うまくアクセスができずコンパイルエラーになってしまいます。 どこが悪いのか分からず困っています。 どなたか助けていただけませんか? mediator.h ----------------------------------------------------- template <class T> class mediator { public: mediator(T* p=NULL) : m_p(p) {} void SetOutClass(T*p) { m_p = pT;} T& GetOutClass() const { return *m_p;} private: T* m_p; }; #define outer GetOutClass() ----------------------------------------------------- COuter.h ----------------------------------------------------- class COuter { private: int m_a; public: void func() { class CInner : public mediator<COuter> { public: CInner(COuter *p) : mediator<COuter>(p) {} void func() { // フレンドクラスなのにアクセスできない!? outer.m_a = 1; } }; CInner inner(this); inner.func(); } friend class mediator<COuter>; }; -----------------------------------------------------

  • 永続化前後のクラスの表現について C#

    ものすごくくだらない質問ですみません。 リレーショナルデータベースを使わざるを得なく、O/Rマッピングツールは使えない状況です。 class Employee があります。 StaffCodeがありますが、将来このコードが重複はありませんが変わる可能性があるので永続化を目的としてこれを主キーとして使えません。 そこで主キーにサロゲートキーを使おうと考えました。 アプリ側で対応するよりもデータベース側でオートナンバーを使います。 一応下記コードでこれから採番する社員と、永続化&採番したあとの社員を表現する事はできます。 しかし同じクラスを使うものなのでしょうか? クラスを分けるべきでしょうか? そもそも考え方がおかしいですか? Class Employee { Public Int Id { get; private set; } Public String Name { get; private set; } Public Int StaffCode { get; private set; } Public Employee(String name, Int staffCode) { this.Name = name; this.StaffCode = staffCode; } Public Employee(Int id, String name, Int staffCode) { this.Id = id; this.Name = name; this.StaffCode = staffCode; } Public Void SetId(Int id) { this.Id = id; } }

専門家に質問してみよう