1

最近、B スプライン曲線をレンダリングするクラスを作成しました。これらの曲線は、多数の制御点によって定義されます。もともと、8 つの制御点を使用するつもりだったので、次のように定数をクラスに追加しました。

class Curve
{
   public:
      static const int CONTROL_POINT_COUNT = 8;
};

ここで、このクラスを拡張して、任意の量のコントロール ポイントを許可したいと考えています。だから私はこれを次のように変更したい:

class Curve
{
   public:
      int getControlPointCount() {return _controlPointCount;}
};

問題は、適応性を容易にするために、最初からメソッドに定数を格納する方がよいのではないかということです。つまり、次のように始めたほうがよいのではないでしょうか。

class Curve
{
   public:
      int getControlPointCount() {return 8;}
};

これの利点は、定数などを移動する代わりに、問題のメソッド内の 1 つのシンボルを変更するだけで済むことです。

これは良い習慣ですか、それとも悪い習慣ですか?

4

9 に答える 9

2
int getControlPointCount() {return _controlPointCount;}

これはアクセサです。litb が指摘したように、アクセサーの const static を交換することは実際には利益ではありません。将来を保証するために本当に必要なのは、おそらくアクセサーとミューテーターのペアです。

int getControlPointCount() {return _controlPointCount;} // accessor

また、アクセサーの design-const を投入して、次のようにします。

int getControlPointCount() const {return _controlPointCount;} // accessor

および対応する:

void setControlPointCount(int cpc) { _controlPointCount = cpc;} //mutator

静的オブジェクトとの大きな違いは、コントロール ポイントの数がクラス レベルの属性ではなく、インスタンス レベルの属性になっていることです。これは設計変更です。このようにしたいですか?

Nit:クラス レベルの静的カウントはpublicアクセサーを必要としないためです。

于 2009-03-15T11:30:04.853 に答える
1

あなたの質問によりよく答えるには、controlPointCount 変数がどのように設定されているかも知っておく必要があります。クラスの外に設定されていますか?この場合、セッターも定義する必要があります。それとも、Curve クラスだけがそれを設定する責任がありますか? コンパイル時または実行時にのみ設定されますか。

とにかく、次の形式でもマジック ナンバーは避けてください。

int getControlPointCount() {return 8;}

これの方が良い:

int getControlPointCount() {return CONTROL_POINT_COUNT;}

メソッドには、クラスの外部に影響を与えることなく、内部実装を変更できるという利点があります (定数値を使用する、構成ファイルから読み取る、値を動的に変更する)。

于 2009-03-15T11:28:14.030 に答える
1

通常、私は可能な限り手動でカップリングを維持することを好みます。

曲線の制御点の数は、曲線の制御点の数です。自由に設定できる独立変数ではありません。

したがって、通常は const 標準コンテナー参照を公開します。

class Curve
{   
    private:
        std::vector<Point>& _controlPoints;

    public:      
        Curve ( const std::vector<Point>& controlPoints) : _controlPoints(controlPoints)
        {
        }

        const std::vector<Point>& getControlPoints ()
        {
            return _controlPoints;
        }
};

また、コントロール ポイントの数を知りたい場合は、 を使用しますcurve.getControlPoints().size()。とにかく、ほとんどのユースケースでは、カウントだけでなくポイントも必要になると思います。標準コンテナーを公開することで、カウントを取得して呼び出すのではなく、標準ライブラリの反復子イディオムと組み込みアルゴリズムを使用できます。getControlPointWithIndexループのような関数。

曲線クラスに他に何もない場合は、次のようにすることもできます。

typedef std::vector<Point> Curve;

(多くの場合、レンダラー クラスはレンダリング パイプラインに関する詳細を保持できるため、曲線自体はレンダリングされず、曲線は純粋にジオメトリック アーティファクトとして残ります)

于 2009-03-15T12:04:38.000 に答える
0

一般に、すべてのデータはプライベートであり、ゲッターとセッターを介してアクセスする必要があります。そうしないと、カプセル化に違反します。つまり、基になるデータを公開すると、自分自身とクラスがその基になるデータの特定の表現にロックされます。

この特定のケースでは、私は次のようなことをしたと思います:

class Curve
{

   protected:

      int getControlPointCount() {return _controlPointCount;}
      int setControlPointCount(int c) { _controlPointCount = c; }

   private:

      static int _controlPointCount = 0;
};
于 2009-03-15T11:33:54.233 に答える
0
class Curve
{   
    private:
        int _controlPointCount;

        void setControlPointCount(int cpc_arg)
        {
            _controlPointCount = cpc_arg;
        }

    public:      
        curve()
        {
            _controlPointCount = 8;
        }

        int getControlPointCount() const
        {
            return _controlPointCount;
        }
};

開発の次の段階に移るまでは、制御点の数をいじることができないように、set 関数を使用してこのようなコードを作成します。実行時に制御点の数を更新するために開始します。その時点で、この set メソッドをプライベート スコープからパブリック スコープに移動できます。

于 2009-03-15T11:34:52.173 に答える
0

質問を理解している間、私は例にいくつかの概念的な問題があります:

  • getControlPointCount()制御点の数を制限しない場合 の戻り値は?
    • MAXINTですか?
    • 曲線上の制御点の現在の数ですか (したがって、これが可能な最大数の点であるという論理を破っていますか?)
  • 実際に MAXINT ポイントで曲線を作成しようとするとどうなりますか? 最終的にメモリ不足になります。

インターフェイス自体に問題があるようです。他の標準コレクション クラスと同様に、クラスはポイント数の制限をカプセル化するAddControlPoint()必要があり、サイズ、メモリ、またはその他の違反が発生した場合はエラーを返す必要があります。

具体的な答えについては、kgiannakakis に同意します。メンバー関数を使用すると、柔軟性が向上します。

于 2009-03-15T12:15:04.463 に答える
0

私は、プログラムの実行を通じて、すべての「安定した」値に対して構成 + 定数 (デフォルト値) を使用する傾向があります。変更できない値 (360 度 -> 2 pi ラジアン、60 秒 -> 1 分) の単純な定数、または変更すると実行中のコードが壊れる (アルゴリズムを不安定にするアルゴリズムの最小値/最大値)。

あなたはいくつかの異なる設計上の問題を扱っています。最初に、コントロール ポイントの数がクラスまたはインスタンス レベルの値であるかどうかを知る必要があります。次に、2 つのレベルのいずれかで定数であるかどうか。

アプリケーションですべての曲線が同じ数の制御点を共有する必要がある場合、それはクラス レベル (静的) 値です。異なる曲線が異なる数の制御点を持つことができる場合、それはクラス レベルの値ではなく、インスタンス レベルの値です。

この場合、コントロール ポイントの数がカーブの存続期間全体にわたって一定である場合、それはインスタンス レベルの定数であり、変化する可能性がある場合は、このレベルでも一定ではありません。

// Assuming that different curves can have different 
// number of control points, but that the value cannot 
// change dynamically for a curve.
class Curve
{
public:
   explicit Curve( int control_points )
      : control_points_( control_points )
   {}
   // ...
private:
   const int control_points_;
};

namespace constant
{
   const int spline_control_points = 8;
}
class Config
{
public:
   Config();
   void readFile( std::string const & file );

   // returns the configured value for SplineControlPoints or
   // constant::spline_control_points if the option does not 
   // appear in config.
   int getSplineControlPoints() const;
};

int main()
{
   Config config;
   config.readFile( "~/.configuration" ); // read config

   Curve c( config.getSplineControlPoints() );
}
于 2009-03-15T12:41:24.137 に答える
0

私が通常使用している整数型の場合:

class Curve
{
   public:
      enum 
      {
          CONTROL_POINT_COUNT = 8
      };
};

クラス実装以外のエンティティに定数が必要ない場合は、 *.cpp ファイルで定数を宣言します。

namespace
{
const int CONTROL_POINT_COUNT = 8;
}
于 2009-03-15T12:54:09.893 に答える
0

通常、定数はメソッド内で定義しないでください。選択した例には、2 つの固有の機能があります。まず、これはゲッターです。次に、返される型は int です。しかし、定数を定義するポイントは、それらを複数回使用し、便利な方法で参照できるようにすることです。「controlPointCount」ではなく「8」と入力すると、時間を節約でき、メンテナンス コストがかからないように見えるかもしれませんが、メソッド内で常に定数を定義する場合、これは通常当てはまりません。

于 2009-03-16T12:22:00.787 に答える