2017-02-24 1 views
-2

コードをモジュール化したい。現時点では、子クラスから親クラスに関数を渡すようにコードを設定しています。しかし、それはまったくコンパイルされません。今私は合格機能をすべて一緒に取り除きたいが、「モジュール性」を保つ。クラス間で関数を渡すことなくC++のモジュール性を維持する

更新:私のコードが何をしているのかについての詳細を追加しました。私はまだ私がやっていることの大半を省いた。クラス分子はクラスレートの複数のインスタンスを最適化しています。クラスレートは、レート内の単一の関数によって生成される複数の値を最適化します。

Class Data_Analysis { 
    virtual double find_rms_A (vector<double>) = 0; 
    virtual double find_rms_B (vector<double>) = 0; 
    virtual double find_rms_C (vector<double>) = 0; 
    double E (double (Data_Analysis::*fxn(vector<double>)) { 
     // doing tons of stuff 
     (this->*fxn)(vec); 
     //Simplex is third party library that requires a function that 
     // takes vector<double> and outputs a double 
     //http://www.codeguru.com/cpp/article.php/c17505/Simplex-Optimization-Algorithm-and-Implemetation-in-C-Programming.htm 
     Simplex((this->*fxn)(vec)); 
    } 
}; 

Class Molecule: Data_Analysis { 
    virtual double find_rms_A (vector<double>) { 
     // using variables only declared in Molecule 
     double rms = 0.0 
     for (int data_point_A = 0; data_point_A < num_data_point_A; data_point_A++) { 
      Rates r(data_point_A); 
      r.run_simulation_v1(); 
      rms += r.return_rate(); 
     } 
     return rms; 
    } 

    virtual double find_rms_B (vector<double>) { 
     // using variables only declared in Molecule 
     double rms = 0.0 
     for (int data_point_B = 0; data_point_B < num_data_point_B; data_point_B++) { 
      //do stuff 
      rms += rate; 
     } 
     return rms; 
    } 
    void optimize_A() { 
     // set variables for type of optimization A 
     E(&Data_Analysis::find_rms_A); 
    } 
    void optimize_B() { 
     // // set variables for type of optimization B 
     E(&Data_Analysis::find_rms_B); 
    } 
}; 

Class Rates: Data_Analysis { 
    virtual double find_rms_C (vector<double>) { 
     // using variables only declared in Rates 
     double rms = 0.0 
     for (int data_point_C = 0; data_point_C < num_data_point_C; data_point_C++) { 
      // run simulation that is completely different than anything used in Molecule 
      rms += rate; 
     } 
     return rms; 
    } 
    void optimize_C() { 
     // set variables for type of optimization C 
     E(&Data_Analysis::find_rms_C); 
    } 
}; 

私は渡す機能を動作させるためにしようとしているもの:

Virtual Function 1Virtual Function 2Virtual Function 3

Pointer Functions 1Pointer Functions 2 "抽象型 'CHILD2' のように変数 'r' を宣言することはできません" : "初期化で" double(Child1 :: )(std :: vector) 'を' Parent :: fxn {別名double()(std :: vector)} 'に変換できません(アスタリスクはイタリック体になっています。 )

したがって、関数を渡すためにコードを再構成したいと思います。しかし、私は「関数E」を取り除き、関数A〜D(モジュール式を破棄する)でコードを繰り返さずにこれをどうやって行うのか分かりません。任意のヒント/アドバイス?

+1

あなたが話していることを示す実際のコードを投稿してください。 –

+1

実装しようとしている実際のユースケースについて詳しく教えてください。あなたの例はあまりにも工夫されているので。 – rustyx

+0

これはXYの問題のようです。あなたはその奇妙さで実際に何を達成しようとしていますか? –

答えて

0

子に固有の関数を渡す場合は、Parentで定義されている仮想関数を使用しないでください。仮想関数を強制終了し、必要な子関数を直接Eに渡します。Child1またはChild2 -nessをラップするためにstd :: bindを使用します。これにより、Eは引数以外の関数を気にしません。

class Parent { 
    double E (std::function<double (vector<double>)> fn) { 
     // doing tons of stuff 
     fn(vec); 
    } 
}; 

class Child1: public Parent { 
    double A (vector<double>) { 
     // using variables only declared in Child1 
    } 
    double B (vector<double>) { 
     // using variables only declared in Child1 
    } 
    void F() { 
     E(std::bind(&Child1::A, this, std::placeholders::_1)); 
     E(std::bind(&Child1::B, this, std::placeholders::_1)); 
    } 
}; 

設計リトマス試験がある:それは子クラスのすべてで仮想関数を実装しても意味がありません場合、それはおそらく1すべきではない...あなたはまた、使用することができ

代わりに呼び出しのラムダ。

また、ベクターを値渡ししてもよろしいですか?代わりにconst参照を渡すことをお勧めします。

0

少なくとも一見、モジュール化されていないコードから問題が発生しているようです。

本当に2つのものを1つのクラスにまとめるように見えます。あなたは、それが使用する個々の計算を実行する何らかの種類の全体的な計算、何かを持っています。

これは、あなたがこれらの一般的な線に沿ってもっと何かしたいな状況のように私には思える:彼らの両方が、本質的に行うため、

// Each derived object only (apparently) needs two functions, so that's 
// what we'll define as the interface: 
struct base { 
    // equivalent to child1::A and B, and to child2::C and D: 
    virtual double A(std::vector<double> const &) = 0; 
    virtual double B(std::vector<double> const &) = 0; 
}; 

// Then a class for the overall computation, using (a pointer to) one of the 
// preceding:  
struct compute { 
    // equivalent to Parent::E(). 
    double E (base *b) { 
     b->A(vec); 
     Simplex(b->A(vec)); 
     b->B(vec); 
     Simplex(b->B(vec)); 
    }  
}; 

struct child1 : public base { 
    // Now each child provides two functions: 
    double A(std::vector<double> const &p) { 
     // do child1 computation A 
    } 
    double B(std::vector<double> const &p) { 
     // do child1 computation B 
    } 

    void F(compute *c) { 
     c->E(this); 
    }   
}; 

struct child2 : public base { 
    double A(std::vector<double> const &p) { 
     // do child2 computation A 
    } 
    double B(std::vector<double> const &p) { 
     // do child2 computation B 
    } 
    void G(compute *c) { 
     c->E(this); 
    }  
}; 

おそらく、child1::F()child2::G()はおそらく、本当に、基底クラスで、単一の関数であることを同じもの。

あなたはどちらかchild1child2オブジェクトへのポインタのコレクションを持っている可能性がある場合(あなたが特定のポインタがchild1child2を参照するか、実行時まで分からない)、あなたが実行したいですこれらのすべてに対して同じ操作を行っても、前の設計が意味を成します。

:特定のインスタンスが child1child2になるかどうか

一方、あなたがコンパイル時にわかっている場合は、仮想関数のオーバーヘッドを避け、テンプレートパラメータとしてchild1child2を渡すことができます

// The class contained only a single function, so it can be just a function: 
template <class F> 
double compute(F const &f) { 
    f.A(vec); 
    Simplex(f.A(vec)); 
    f.B(vec); 
    Simplex(f.B(vec)); 
} 

class child1 { // no longer needs a common base class 
    double A(std::vector<double> const &); 
    double B(std::vector<double> const &); 
    void F() { compute(this); } 
}; 

class child2 { // no longer needs a common base class 
    double A(std::vector<double> const &); 
    double B(std::vector<double> const &); 
    void G() { compute(this); } 
}; 
+0

私の質問が更新されました。私はあなたがやっていることすべてを読んだことはありませんが、私のアップデートはあなたのソリューションと競合していると思います。 –

関連する問題