2012-01-27 22 views
4

私は主に見せかけstruct秒であり、組成物による相互に依存しているCUDAプロジェクト内のクラスの束を持っている:カプセル化と構造化 - これは悪いスタイルと考えられますか?

class A { 
    public: 
     typedef boost::shared_ptr<A> Ptr; 
     A(uint n_elements) { ... // allocate element_indices }; 
     DeviceVector<int>::iterator get_element_indices(); 
    private: 
     DeviceVector<int> element_indices; 
} 

class B { 
    public: 
     B(uint n_elements) { 
      ... // initialize members 
     }; 
     A::Ptr get_a(); 
     DevicePointer<int>::iterator get_other_stuff(); 
    private: 
     A::Ptr a; 
     DeviceVector<int> other_stuff; 
} 

DeviceVectorthrust::device_vectorの単なるラッパーであると::iteratorはにキャストすることができます生のデバイスポインタ。カスタムカーネルが呼び出され、デバイスメモリへのハンドルが必要になるため、これが必要です。 ABを使用してクラスがGPU上でカスタムカーネルを実行できるように

さて、私はカプセル化を気にしますが、データへ

  • 生のポインタんが
  • 、公開する必要がデフォルトコンストラクタがあります望ましくない、デバイスメモリを自動的に割り当てられなければならない - >shared_ptr<T>
  • ABにごく少数の方法が
を必要としています

ので、一つは単純に使用して、構造体

struct A { 
    void initialize(uint n_elements); 
    DeviceVector<int> element_indices; 
} 

struct B { 
    void initialize(uint n_elements); 
    A a; 
    DeviceVector<int> other_stuff; 
} 

私はカプセル化の意味で、これは実質的に同等であることを正しいですか思ったんだけどによりはるかに簡単な生活を作ることができます。もしそうなら、全体のコンセプトに間違っていることがあり、ある時点で噛む可能性がありますか?

+4

C++のクラスと構造体の唯一の違いは、デフォルトの可視性(クラスのprivate、structのpublic)です。コンパイラは、何も指定しなければデフォルトのコンストラクタを与えます。したがって、あなたの構造体例の初期化関数の目的がわかりません。 – jpm

+2

あなたの質問は本当に "カプセル化対公開データ"について質問しています。 jpmは 'struct'を使うのは正しいです。 –

+0

"class"と "struct"という単語は、オブジェクトデザインの意味合いが少し強くなっています。これらの用語を混乱させる原因はC++です。 :) –

答えて

1

これはトレードオフです。

値の構造体を使用すると、一連のデータをまとめることができます。多くのヘルパールーチンをタックして、意図した使い方以外に依存させると、非常にクルージングになることがあります。いつ、どのようにそれらを使用するかについて、あなた自身に厳格にしてください。これらのオブジェクトにゼロメソッドを持たせることは、これを自分自身に明白にする良い方法です。

問題を解決するために使用するクラスがいくつかあるかもしれません。私はそれをモジュールと呼んでいます。モジュール内に価値の構造体を持つことは、簡単に論ずることができます。モジュールの外では、良い動作を望む必要があります。彼らに厳密なインターフェースがないので、コンパイラが誤用を警告することを願ってください。

このステートメントが与えられていると、匿名または詳細の名前空間ではより適切だと思います。彼らがパブリックインターフェイスになると、人々はそれらに砂糖を加える傾向があります。砂糖を削除するか、それをリファクタリングしてインタフェースを持つ第1クラスのオブジェクトにします。

私は彼らがconstオブジェクトとしてより適切だと思います。あなたが陥る問題は、あなたがこの生涯にわたって使用されているこの「物体」の不変性をどこでも維持している(しようとしている)ことです。異なるレベルの抽象化がわずかな変異でそれらを必要とする場合は、コピーを作成してください。名前付きパラメータイディオムはこれに適しています。

Domain Driven Designは、対象に対して慎重で完全な治療を与える。それは、それを理解し、デザインを容易にする方法のより実用的な特徴である。

Clean Codeも、別の観点から議論します。それはmorality本以上です。

どちらもすばらしい本ですが、このトピックの外では一般的にお勧めします。

+0

あなたの答えをありがとう、私は基本的に方法がない '構造体'が少なくともクラス 'class'とは対照的に自分自身にどのように見えるかについて同じ考えを持っています。これらの 'struct'を名前空間に入れる(あるいは、それらを使う唯一のクラスへの可視性を制限するのか? – bbtrb

2

簡単にします。必要になる前に抽象化とカプセル化を導入しないでください。

2

データメンバーを常に非公開にすることは良い習慣です。最初は、構造体が小さく、メンバー関数がなくても、メンバー関数がいくつかあり、データメンバーを公開する必要があるようです。しかし、あなたのプログラムが進化するにつれ、これらの "構造体"は成長し、増殖する傾向があります。コードを知る前に、すべてのコードはこれらの構造体の内部構造に依存しており、コードベース全体にわずかな変更が反映されます。

データに未処理のポインタを公開する必要がある場合でも、ゲッターを使用して未処理のポインタを公開することをお勧めします。データの内部処理方法を変更することができます。 g。生の配列をstd :: vectorに置き換えます。データメンバーがプライベートで、ゲッターを使用している場合は、クラスを使用するコードに影響を与えずに行うことができます。さらに、getterを使用すると、constポインタを返すことで定数を強制し、特定のデータを読み取り専用にすることができます。

これはもう少し作業が進んでいますが、ほとんどの場合、長期的には報酬があります。

関連する問題