4

次のクラス階層があります。

class Base { // This class cannot be modified
public:
  Base(int a, int b, int c) {
     if ( a == 100 && b == 200 && c < 100  ) // whatever condition
       throw "Error!";
  }
};

class Derived : public Base { // this class can be modified
public:
   Derived(int a, int b, int c) : Base(a, b, c) {}
};

class Derived はコードの多くの場所で使用されるため、ある種のファクトリ関数に置き換えることはできません。

問題は、Base コンストラクターを呼び出す前に a、b、c の値を修正できるコンストラクトがあるかどうかです。

次のような関数を使用できることを知っています。

   Derived(int a, int b, int c) : Base(FixA(a), FixB(b), FixC(c)) {}

   int FixA(int a) { /*fix a value*/ return a; }
   int FixB(int b) { /*fix b value*/ return b; }
   int FixC(int c) { /*fix c value*/ return c; }

ただし、上記の基本クラスの c-tor の例のように abc 値が依存している場合、正しい値を設定することはできません。

これを次のように拡張することを考えていました:

   Derived(int a, int b, int c) : Base(FixA(a,b,c), FixB(a,b,c), FixC(a,b,c)) {}

   int FixA(int a, int& b, int& c) { /*fix a b c values*/ return a; }
   int FixB(int& a, int b, int& c) { /*fix a b c values*/ return b; }
   int FixC(int& a, int& b, int c) { /*fix a b c values*/ return c; }

修正が既に行われたことを示す何らかのフラグもあるはずです。これが実際に正しい c++ であるかどうかはわかりません。

最善の解決策は、実際に例外をキャッチすることです。

4

3 に答える 3

8

と の間にクラスを挿入することを検討してDerivedくださいBase

class Derived: public UnpackToBase {
public:
    Derived(int a, int b, int c): UnpackToBase(FixParameters(a, b, c))

class UnpackToBase: public Base {
public:
    UnpackToBase(FixParameters params): Base(params.a, params.b, params.c)

struct FixParameters {
    int a, b, c;
    FixParameters(int a, int b, int c): a(a), b(b), c(c) {
         // do stuff
    }

C++11 では、次の委譲コンストラクターを使用できますDerived

class Derived: public Base {
public:
    Derived(int a, int b, int c): Derived(FixParameters(a, b, c)) { }
    Derived(FixParameters params): Base(params.a, params.b, params.c) { }
于 2012-08-06T13:38:39.957 に答える
1

これを解決するには、シングルトン パターンを使用できます。以下のコードを参照してください。ここでは、構築初期化リストの初期化の順序は重要ではありません。ただ、これがエレガントと言えるのかは疑問です。

class Base 
{ 
    // This class cannot be modified 
public:   Base(int a, int b, int c) 
          {      
              if ( a == 100 && b == 200 && c < 100  ) // whatever condition
                  throw "Error!";   
          } 
};  

class Validator
{
public:

    static Validator& instance(int a_in, int b_in, int c_in)
    {
        static Validator v(a_in,b_in,c_in);

        return v;
    }



    int& a(){ return m_a;}
    int& b(){ return m_b;}
    int& c(){ return m_c;}

private:

    Validator(int a_in, int b_in, int c_in) : m_a(a_in), m_b(b_in), m_c(c_in)
    {
        //  perform validation and modify the members
        //  Example validation
        if(m_a > 0 && m_b > 0)
        {
            m_c = 0;
        }
    }

    int m_a;
    int m_b;
    int m_c;
};

class Derived : public Base 
{ 
    // this class can be modified 
public:    
    Derived(int a, int b, int c) : Base(Validator::instance(a, b, c).a(), Validator::instance(a, b, c).b(), Validator::instance(a, b, c).c())
    {} 
};

int _tmain(int argc, _TCHAR* argv[])
{
    Derived d(1,2,3);

    return 0;
}
于 2012-08-06T13:42:53.710 に答える
0

何か奇妙なことを起こさなければならないものをハッキングすることに問題がないように見えるので、良い「オールマクロ」を使用してみませんか..

#define FIX_ME(x) //do something
Derived(int a, int b, int c) : Base(FIX_ME(a), FIX_ME(b), FIX_ME(c)) {}
于 2012-08-06T13:18:06.717 に答える