0

私のプログラムには、次のような Car および CarManager クラスがあります。

#include <list>

class Car
{
public:
    void Draw() { Draw(m_opacity); }
    void Draw(float opacity)
    {
    }

private:
    float m_opacity;
};

class CarManager
{
public:
    //Draw cars using their m_opacity member
    void DrawCars() 
    { 
        for(auto i = m_cars.begin(); i != m_cars.end(); i++)
            i->Draw();
    }

    //Draw cars using opacity argument
    void DrawCars(float opacity)
    {
        for(auto i = m_cars.begin(); i != m_cars.end(); i++)
            i->Draw(opacity);
    }

private:
    std::list<Car> m_cars;
}

MyApplication::OnRender()
{
    CarManager* pCarManager = GetCarManager();

    //If this condition is met, I want all cars to be drawn with 0.5 opacity.
    if(condition)
        pCarManager->DrawCars(0.5f);

    //Otherwise, draw cars using their m_opacity value.     
    else
        pCarManager->DrawCars();
}

C++ では、非静的メンバーを既定の引数として使用することは許可されていないため、Drawing 関数をオーバーロードしました。引数が指定されていない場合、オーバーロードされたバージョンの関数がクラス メンバーを使用して呼び出されます。

各車には、レンダリングに使用される m_opacity メンバーがあります。ただし、すべての車で使用する不透明度の値を指定したい場合があります。これらの場合、私が提供する値を優先して m_opacity を無視したいと思います。

この例では、CarManager::DrawCars() のレンダリング コードはかなり小さいので、Car::Draw() への別の呼び出しで同じコードを繰り返しても大したことではありません。しかし、私の実際のプログラムでは、同じコードをすべて繰り返すことは実用的ではありません。

これは面倒になり始めています。これについてもっと良い方法はありますか?

4

2 に答える 2

2

簡単な方法は、魔法の値を使用することです。

#include <list>

class Car
{
public:
    static float noOpacity() { return -1; }

    void Draw(float opacity)
    {
        if (opacity==noOpacity()) {
            opacity = m_opacity;
        }
        // etc.
    }

private:
    float m_opacity;
};

class CarManager
{
public:
    //Draw cars using optional opacity argument
    void DrawCars(float opacity = Car::noOpacity(); )
    {
        for(auto i = m_cars.begin(); i != m_cars.end(); i++)
            i->Draw(opacity);
    }

private:
    std::list<Car> m_cars;
}
于 2012-11-12T01:53:07.997 に答える
0

この問題に対処するには、いくつかの方法があります。

  1. 別の回答で指摘されているように、特別な値を使用して、デフォルトを使用する必要があることを示すことができます。データ型が明らかな特別な値をサポートしている場合、これは正しい解決策かもしれませんが、すべての型で機能するわけではなく、実際には保守が比較的困難です。「不可能な」値が最終的に可能になり、未定義の動作が発生する製品コードのケースを見てきました (たとえば、債券の利回りは常に正であると考えられていましたが、債券の利回りが負になる可能性があることが判明しました)。
  2. オブジェクトが実際に存在するかどうかを示すoptional<T>a を基本的にバンドルするan を使用すると、1 つの特別な値が処理されます。T選択が実際にバイナリ (渡された不透明度またはオブジェクトの不透明度を使用) である場合、これは機能します。デフォルトではoptional<T>、オプションの引数が存在しないことを示す が使用され、それ以外の場合はその値が使用されます。
  3. よりスケーラブルなバージョンは、オブジェクトで呼び出してオブジェクトの不透明度を決定する関数を渡すことCarです: std::function<double(Car const&)>. デフォルトは の不透明度を取得する関数ですがCar、常に定数を返すなど、他の関数にすることもできます。

3 番目のオプションはもう少しあいまいなので、以下に例を示します (これは、の不透明度を返すCarメンバー関数があることを前提としています)。opacity()Car

void Car::Draw(std::function<double(Car const&)> getOpacity
                     = std::mem_fn(&Car::opacity)) {
    opacity = getOpacity(*this);
    // ...
}

不透明度を何らかの方法でコピーして、他の関数オブジェクトを簡単に渡すことができるようになりました。

double ConstantOpacity(Car const&, double value) { return value; }
double ComputeOpacity(Car const& c, double value) { return (c.opacity() + value) / 2; }

Car* car = ...;
car->Draw(std::bind(&Car::opacity, _1));        // use the car's opacity
car->Draw(std::bind(&ConstantOpacity, _1, 0.5); // use opacity 0.5
car->Draw(std::bind(&ComputeOpacity, _1, 0.5);  // average of the car's opacity and 0.5
于 2012-11-12T02:19:28.780 に答える